/[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 62 - (show annotations) (download)
Tue Sep 7 11:08:22 2010 UTC (9 years, 11 months ago) by william
File size: 6522 byte(s)
Auto Commited Import of: pcsx2-0.9.7-r3738-debug 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 bool ret;
111
112 if (vif0.vifstalled)
113 ret = VIF0transfer((u32*)ptag + (2 + vif0.irqoffset), 2 - vif0.irqoffset); //Transfer Tag on stall
114 else
115 ret = VIF0transfer((u32*)ptag + 2, 2); //Transfer Tag
116
117 if ((ret == false) && vif0.irqoffset < 2)
118 {
119 vif0.inprogress = 0; //Better clear this so it has to do it again (Jak 1)
120 return; //There has been an error or an interrupt
121 }
122 }
123
124 vif0.irqoffset = 0;
125 vif0.done |= hwDmacSrcChainWithStack(vif0ch, ptag->ID);
126
127 if(vif0ch.qwc > 0) vif0.inprogress = 1;
128 //Check TIE bit of CHCR and IRQ bit of tag
129 if (vif0ch.chcr.TIE && ptag->IRQ)
130 {
131 VIF_LOG("dmaIrq Set");
132
133 //End Transfer
134 vif0.done = true;
135 return;
136 }
137 break;
138 }
139 }
140
141 __fi void vif0Interrupt()
142 {
143 VIF_LOG("vif0Interrupt: %8.8x", cpuRegs.cycle);
144
145 g_vifCycles = 0;
146
147 if (!(vif0ch.chcr.STR)) Console.WriteLn("vif0 running when CHCR == %x", vif0ch.chcr._u32);
148
149 if (vif0.cmd)
150 {
151 if(vif0.done == true && vif0ch.qwc == 0) vif0Regs.stat.VPS = VPS_WAITING;
152 }
153 else
154 {
155 vif0Regs.stat.VPS = VPS_IDLE;
156 }
157
158 if (vif0.irq && vif0.tag.size == 0)
159 {
160 vif0Regs.stat.INT = true;
161 hwIntcIrq(VIF0intc);
162 --vif0.irq;
163 if (vif0Regs.stat.test(VIF0_STAT_VSS | VIF0_STAT_VIS | VIF0_STAT_VFS))
164 {
165 vif0Regs.stat.FQC = 0;
166
167 // One game doesn't like vif stalling at end, can't remember what. Spiderman isn't keen on it tho
168 //vif0ch.chcr.STR = false;
169 if(vif0ch.qwc > 0 || !vif0.done) return;
170 }
171 }
172
173 if (vif0.inprogress & 0x1)
174 {
175 _VIF0chain();
176 CPU_INT(DMAC_VIF0, g_vifCycles);
177 return;
178 }
179
180 if (!vif0.done)
181 {
182
183 if (!(dmacRegs.ctrl.DMAE))
184 {
185 Console.WriteLn("vif0 dma masked");
186 return;
187 }
188
189 if ((vif0.inprogress & 0x1) == 0) vif0SetupTransfer();
190
191 CPU_INT(DMAC_VIF0, g_vifCycles);
192 return;
193 }
194
195 if (vif0.vifstalled && vif0.irq)
196 {
197 DevCon.WriteLn("VIF0 looping on stall\n");
198 CPU_INT(DMAC_VIF0, 0);
199 return; //Dont want to end if vif is stalled.
200 }
201 #ifdef PCSX2_DEVBUILD
202 if (vif0ch.qwc > 0) Console.WriteLn("vif0 Ending with %x QWC left");
203 if (vif0.cmd != 0) Console.WriteLn("vif0.cmd still set %x tag size %x", vif0.cmd, vif0.tag.size);
204 #endif
205
206 vif0ch.chcr.STR = false;
207 g_vifCycles = 0;
208 hwDmacIrq(DMAC_VIF0);
209 vif0Regs.stat.FQC = 0;
210 }
211
212 void dmaVIF0()
213 {
214 VIF_LOG("dmaVIF0 chcr = %lx, madr = %lx, qwc = %lx\n"
215 " tadr = %lx, asr0 = %lx, asr1 = %lx",
216 vif0ch.chcr._u32, vif0ch.madr, vif0ch.qwc,
217 vif0ch.tadr, vif0ch.asr0, vif0ch.asr1);
218
219 g_vifCycles = 0;
220 g_vu0Cycles = 0;
221 //if(vif0.irqoffset != 0 && vif0.vifstalled == true) DevCon.Warning("Offset on VIF0 start! offset %x, Progress %x", vif0.irqoffset, vif0.vifstalled);
222 /*vif0.irqoffset = 0;
223 vif0.vifstalled = false;
224 vif0.inprogress = 0;
225 vif0.done = false;*/
226
227 if ((vif0ch.chcr.MOD == NORMAL_MODE) || vif0ch.qwc > 0) // Normal Mode
228 {
229 vif0.dmamode = VIF_NORMAL_TO_MEM_MODE;
230
231 vif0.done = false;
232
233 if(vif0ch.chcr.MOD == CHAIN_MODE && vif0ch.qwc > 0)
234 {
235 vif0.dmamode = VIF_CHAIN_MODE;
236 DevCon.Warning(L"VIF0 QWC on Chain CHCR " + vif0ch.chcr.desc());
237
238 if ((vif0ch.chcr.tag().ID == TAG_REFE) || (vif0ch.chcr.tag().ID == TAG_END))
239 {
240 vif0.done = true;
241 }
242 }
243 }
244 else
245 {
246 vif0.dmamode = VIF_CHAIN_MODE;
247 vif0.done = false;
248 }
249
250 vif0Regs.stat.FQC = min((u16)0x8, vif0ch.qwc);
251
252 //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),
253 //the first bit it sends isnt required for it to work.
254 //Also being an end chain it ignores the second lot, this causes infinite loops ;p
255 // Chain Mode
256 CPU_INT(DMAC_VIF0, 4);
257 }

  ViewVC Help
Powered by ViewVC 1.1.22