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

Contents of /trunk/pcsx2/Vif0_Dma.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 273 - (show annotations) (download)
Fri Nov 12 01:10:22 2010 UTC (9 years, 3 months ago) by william
File size: 7196 byte(s)
Auto Commited Import of: pcsx2-0.9.7-DEBUG (upstream: v0.9.7.4013 local: v0.9.7.197-latest) in ./trunk
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 "VUmicro.h"
20 #include "newVif.h"
21
22 // Run VU0 until finish, don't add cycles to EE
23 // because its vif stalling not the EE core...
24 __fi void vif0FLUSH()
25 {
26 if(g_packetsizeonvu > vif0.vifpacketsize && g_vu0Cycles > 0)
27 {
28 //DevCon.Warning("Adding on same packet");
29 if( ((g_packetsizeonvu - vif0.vifpacketsize) >> 1) > g_vu0Cycles)
30 g_vu0Cycles -= (g_packetsizeonvu - vif0.vifpacketsize) >> 1;
31 else g_vu0Cycles = 0;
32 }
33 if(g_vu0Cycles > 0)
34 {
35 //DevCon.Warning("Adding %x cycles to VIF0", g_vu1Cycles * BIAS);
36 g_vifCycles += g_vu0Cycles;
37 g_vu0Cycles = 0;
38 }
39 g_vu0Cycles = 0;
40 if (!(VU0.VI[REG_VPU_STAT].UL & 1)) return;
41 if(VU0.flags & VUFLAG_MFLAGSET)
42 {
43 vif0.vifstalled = true;
44 return;
45 }
46 int _cycles = VU0.cycle;
47 vu0Finish();
48 //DevCon.Warning("VIF0 adding %x cycles", (VU0.cycle - _cycles) * BIAS);
49 g_vifCycles += (VU0.cycle - _cycles) * BIAS;
50 return;
51 }
52
53 bool _VIF0chain()
54 {
55 u32 *pMem;
56
57 if (vif0ch.qwc == 0)
58 {
59 vif0.inprogress = 0;
60 return true;
61 }
62
63 pMem = (u32*)dmaGetAddr(vif0ch.madr, false);
64 if (pMem == NULL)
65 {
66 vif0.cmd = 0;
67 vif0.tag.size = 0;
68 vif0ch.qwc = 0;
69 return true;
70 }
71
72 VIF_LOG("VIF0chain size=%d, madr=%lx, tadr=%lx",
73 vif0ch.qwc, vif0ch.madr, vif0ch.tadr);
74
75 if (vif0.vifstalled)
76 return VIF0transfer(pMem + vif0.irqoffset, vif0ch.qwc * 4 - vif0.irqoffset);
77 else
78 return VIF0transfer(pMem, vif0ch.qwc * 4);
79 }
80
81 __fi void vif0SetupTransfer()
82 {
83 tDMA_TAG *ptag;
84
85 switch (vif0.dmamode)
86 {
87 case VIF_NORMAL_TO_MEM_MODE:
88 vif0.inprogress = 1;
89 vif0.done = true;
90 g_vifCycles = 2;
91 break;
92
93 case VIF_CHAIN_MODE:
94 ptag = dmaGetAddr(vif0ch.tadr, false); //Set memory pointer to TADR
95
96 if (!(vif0ch.transfer("vif0 Tag", ptag))) return;
97
98 vif0ch.madr = ptag[1]._u32; //MADR = ADDR field + SPR
99 g_vifCycles += 1; // Add 1 g_vifCycles from the QW read for the tag
100
101 // Transfer dma tag if tte is set
102
103 VIF_LOG("vif0 Tag %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx",
104 ptag[1]._u32, ptag[0]._u32, vif0ch.qwc, ptag->ID, vif0ch.madr, vif0ch.tadr);
105
106 vif0.inprogress = 0;
107
108 if (vif0ch.chcr.TTE)
109 {
110 // Transfer dma tag if tte is set
111
112 bool ret;
113
114 static __aligned16 u128 masked_tag;
115
116 masked_tag._u64[0] = 0;
117 masked_tag._u64[1] = *((u64*)ptag + 1);
118
119 VIF_LOG("\tVIF0 SrcChain TTE=1, data = 0x%08x.%08x", masked_tag._u32[3], masked_tag._u32[2]);
120
121 if (vif0.vifstalled)
122 {
123 ret = VIF0transfer((u32*)&masked_tag + vif0.irqoffset, 4 - vif0.irqoffset, true); //Transfer Tag on stall
124 //ret = VIF0transfer((u32*)ptag + (2 + vif0.irqoffset), 2 - vif0.irqoffset); //Transfer Tag on stall
125 }
126 else
127 {
128 //Some games (like killzone) do Tags mid unpack, the nops will just write blank data
129 //to the VU's, which breaks stuff, this is where the 128bit packet will fail, so we ignore the first 2 words
130 vif0.irqoffset = 2;
131 ret = VIF0transfer((u32*)&masked_tag + 2, 2, true); //Transfer Tag
132 //ret = VIF0transfer((u32*)ptag + 2, 2); //Transfer Tag
133 }
134
135 if (!ret && vif0.irqoffset)
136 {
137 vif0.inprogress = 0; //Better clear this so it has to do it again (Jak 1)
138 return; //IRQ set by VIFTransfer
139
140 }
141 }
142
143 vif0.irqoffset = 0;
144 vif0.done |= hwDmacSrcChainWithStack(vif0ch, ptag->ID);
145
146 if(vif0ch.qwc > 0) vif0.inprogress = 1;
147 //Check TIE bit of CHCR and IRQ bit of tag
148 if (vif0ch.chcr.TIE && ptag->IRQ)
149 {
150 VIF_LOG("dmaIrq Set");
151
152 //End Transfer
153 vif0.done = true;
154 return;
155 }
156 break;
157 }
158 }
159
160 __fi void vif0Interrupt()
161 {
162 VIF_LOG("vif0Interrupt: %8.8x", cpuRegs.cycle);
163
164 g_vifCycles = 0;
165
166 if (!(vif0ch.chcr.STR)) Console.WriteLn("vif0 running when CHCR == %x", vif0ch.chcr._u32);
167
168 if (vif0.cmd)
169 {
170 if(vif0.done == true && vif0ch.qwc == 0) vif0Regs.stat.VPS = VPS_WAITING;
171 }
172 else
173 {
174 vif0Regs.stat.VPS = VPS_IDLE;
175 }
176
177 if (vif0.irq && vif0.tag.size == 0)
178 {
179 vif0Regs.stat.INT = true;
180 hwIntcIrq(VIF0intc);
181 --vif0.irq;
182 if (vif0Regs.stat.test(VIF0_STAT_VSS | VIF0_STAT_VIS | VIF0_STAT_VFS))
183 {
184 vif0Regs.stat.FQC = 0;
185
186 // One game doesn't like vif stalling at end, can't remember what. Spiderman isn't keen on it tho
187 //vif0ch.chcr.STR = false;
188 if(vif0ch.qwc > 0 || !vif0.done) return;
189 }
190 }
191
192 if (vif0.inprogress & 0x1)
193 {
194 _VIF0chain();
195 CPU_INT(DMAC_VIF0, g_vifCycles);
196 return;
197 }
198
199 if (!vif0.done)
200 {
201
202 if (!(dmacRegs.ctrl.DMAE))
203 {
204 Console.WriteLn("vif0 dma masked");
205 return;
206 }
207
208 if ((vif0.inprogress & 0x1) == 0) vif0SetupTransfer();
209
210 CPU_INT(DMAC_VIF0, g_vifCycles);
211 return;
212 }
213
214 if (vif0.vifstalled && vif0.irq)
215 {
216 DevCon.WriteLn("VIF0 looping on stall\n");
217 CPU_INT(DMAC_VIF0, 0);
218 return; //Dont want to end if vif is stalled.
219 }
220 #ifdef PCSX2_DEVBUILD
221 if (vif0ch.qwc > 0) Console.WriteLn("vif0 Ending with %x QWC left");
222 if (vif0.cmd != 0) Console.WriteLn("vif0.cmd still set %x tag size %x", vif0.cmd, vif0.tag.size);
223 #endif
224
225 vif0ch.chcr.STR = false;
226 g_vifCycles = 0;
227 hwDmacIrq(DMAC_VIF0);
228 vif0Regs.stat.FQC = 0;
229 }
230
231 void dmaVIF0()
232 {
233 VIF_LOG("dmaVIF0 chcr = %lx, madr = %lx, qwc = %lx\n"
234 " tadr = %lx, asr0 = %lx, asr1 = %lx",
235 vif0ch.chcr._u32, vif0ch.madr, vif0ch.qwc,
236 vif0ch.tadr, vif0ch.asr0, vif0ch.asr1);
237
238 g_vifCycles = 0;
239 g_vu0Cycles = 0;
240 //if(vif0.irqoffset != 0 && vif0.vifstalled == true) DevCon.Warning("Offset on VIF0 start! offset %x, Progress %x", vif0.irqoffset, vif0.vifstalled);
241 /*vif0.irqoffset = 0;
242 vif0.vifstalled = false;
243 vif0.inprogress = 0;
244 vif0.done = false;*/
245
246 if ((vif0ch.chcr.MOD == NORMAL_MODE) || vif0ch.qwc > 0) // Normal Mode
247 {
248 vif0.dmamode = VIF_NORMAL_TO_MEM_MODE;
249
250 vif0.done = false;
251
252 if(vif0ch.chcr.MOD == CHAIN_MODE && vif0ch.qwc > 0)
253 {
254 vif0.dmamode = VIF_CHAIN_MODE;
255 DevCon.Warning(L"VIF0 QWC on Chain CHCR " + vif0ch.chcr.desc());
256
257 if ((vif0ch.chcr.tag().ID == TAG_REFE) || (vif0ch.chcr.tag().ID == TAG_END))
258 {
259 vif0.done = true;
260 }
261 }
262 }
263 else
264 {
265 vif0.dmamode = VIF_CHAIN_MODE;
266 vif0.done = false;
267 }
268
269 vif0Regs.stat.FQC = min((u16)0x8, vif0ch.qwc);
270
271 //Using a delay as Beyond Good and Evil does the DMA twice with 2 different TADR's (no checks in the middle, all one block of code),
272 //the first bit it sends isnt required for it to work.
273 //Also being an end chain it ignores the second lot, this causes infinite loops ;p
274 // Chain Mode
275 CPU_INT(DMAC_VIF0, 4);
276 }

  ViewVC Help
Powered by ViewVC 1.1.22