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

Contents of /trunk/pcsx2/Vif.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 62 - (show annotations) (download)
Tue Sep 7 11:08:22 2010 UTC (10 years, 2 months ago) by william
File size: 10325 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.h"
19 #include "Vif_Dma.h"
20 #include "newVif.h"
21 #include "GS.h"
22 #include "Gif.h"
23
24 vifStruct vif0;
25 vifStruct vif1;
26 tGSTransferStatus GSTransferStatus((STOPPED_MODE<<8) | (STOPPED_MODE<<4) | STOPPED_MODE);
27
28 void vif0Reset()
29 {
30 /* Reset the whole VIF, meaning the internal pcsx2 vars and all the registers */
31 memzero(vif0);
32 memzero(vif0Regs);
33
34 psHu64(VIF0_FIFO) = 0;
35 psHu64(VIF0_FIFO + 8) = 0;
36
37 vif0Regs.stat.VPS = VPS_IDLE;
38 vif0Regs.stat.FQC = 0;
39
40 vif0.done = false;
41
42 resetNewVif(0);
43 }
44
45 void vif1Reset()
46 {
47 /* Reset the whole VIF, meaning the internal pcsx2 vars, and all the registers */
48 memzero(vif1);
49 memzero(vif1Regs);
50
51 psHu64(VIF1_FIFO) = 0;
52 psHu64(VIF1_FIFO + 8) = 0;
53
54 vif1Regs.stat.VPS = VPS_IDLE;
55 vif1Regs.stat.FQC = 0; // FQC=0
56
57 vif1.done = false;
58 cpuRegs.interrupt &= ~((1 << 1) | (1 << 10)); //Stop all vif1 DMA's
59
60 resetNewVif(1);
61 }
62
63 void SaveStateBase::vif0Freeze()
64 {
65 FreezeTag("VIFdma");
66 Freeze(g_vifCycles); // Dunno if this one is needed, but whatever, it's small. :)
67 Freeze(g_vifmask); // mask settings for VIF0 and VIF1
68 Freeze(vif0);
69
70 Freeze(nVif[0].bSize);
71 FreezeMem(nVif[0].buffer, nVif[0].bSize);
72 }
73
74 void SaveStateBase::vif1Freeze()
75 {
76 Freeze(vif1);
77
78 Freeze(nVif[1].bSize);
79 FreezeMem(nVif[1].buffer, nVif[1].bSize);
80 }
81
82 //------------------------------------------------------------------
83 // Vif0/Vif1 Write32
84 //------------------------------------------------------------------
85
86 extern bool _chainVIF0();
87 extern bool _VIF0chain();
88
89 __fi void vif0FBRST(u32 value) {
90 VIF_LOG("VIF0_FBRST write32 0x%8.8x", value);
91
92 if (value & 0x1) // Reset Vif.
93 {
94 //Console.WriteLn("Vif0 Reset %x", vif0Regs.stat._u32);
95
96 memzero(vif0);
97 vif0ch.qwc = 0; //?
98 cpuRegs.interrupt &= ~1; //Stop all vif0 DMA's
99 psHu64(VIF0_FIFO) = 0;
100 psHu64(VIF0_FIFO + 8) = 0;
101 vif0.done = false;
102 vif0Regs.err.reset();
103 vif0Regs.stat.clear_flags(VIF0_STAT_FQC | VIF0_STAT_INT | VIF0_STAT_VSS | VIF0_STAT_VIS | VIF0_STAT_VFS | VIF0_STAT_VPS); // FQC=0
104 }
105
106 /* Fixme: Forcebreaks are pretty unknown for operation, presumption is it just stops it what its doing
107 usually accompanied by a reset, but if we find a broken game which falls here, we need to see it! (Refraction) */
108 if (value & 0x2) // Forcebreak Vif,
109 {
110 /* I guess we should stop the VIF dma here, but not 100% sure (linuz) */
111 cpuRegs.interrupt &= ~1; //Stop all vif0 DMA's
112 vif0Regs.stat.VFS = true;
113 vif0Regs.stat.VPS = VPS_IDLE;
114 Console.WriteLn("vif0 force break");
115 }
116
117 if (value & 0x4) // Stop Vif.
118 {
119 // Not completely sure about this, can't remember what game, used this, but 'draining' the VIF helped it, instead of
120 // just stoppin the VIF (linuz).
121 vif0Regs.stat.VSS = true;
122 vif0Regs.stat.VPS = VPS_IDLE;
123 vif0.vifstalled = true;
124 }
125
126 if (value & 0x8) // Cancel Vif Stall.
127 {
128 bool cancel = false;
129
130 /* Cancel stall, first check if there is a stall to cancel, and then clear VIF0_STAT VSS|VFS|VIS|INT|ER0|ER1 bits */
131 if (vif0Regs.stat.test(VIF0_STAT_VSS | VIF0_STAT_VIS | VIF0_STAT_VFS))
132 cancel = true;
133
134 vif0Regs.stat.clear_flags(VIF0_STAT_VSS | VIF0_STAT_VFS | VIF0_STAT_VIS |
135 VIF0_STAT_INT | VIF0_STAT_ER0 | VIF0_STAT_ER1);
136 if (cancel)
137 {
138 if (vif0.vifstalled)
139 {
140 g_vifCycles = 0;
141
142 // loop necessary for spiderman
143 //vif0ch.chcr.STR = true;
144 if(vif0ch.chcr.STR) CPU_INT(DMAC_VIF0, 0); // Gets the timing right - Flatout
145 }
146 }
147 }
148 }
149
150 __fi void vif1FBRST(u32 value) {
151 VIF_LOG("VIF1_FBRST write32 0x%8.8x", value);
152
153 if (FBRST(value).RST) // Reset Vif.
154 {
155 memzero(vif1);
156 //cpuRegs.interrupt &= ~((1 << 1) | (1 << 10)); //Stop all vif1 DMA's
157 vif1ch.qwc -= min((int)vif1ch.qwc, 16); //?
158 psHu64(VIF1_FIFO) = 0;
159 psHu64(VIF1_FIFO + 8) = 0;
160 //vif1.done = false;
161
162
163 //DevCon.Warning("VIF FBRST Reset MSK = %x", vif1Regs.mskpath3);
164 if(vif1Regs.mskpath3 == 1 && GSTransferStatus.PTH3 == STOPPED_MODE && gifch.chcr.STR == true)
165 {
166 //DevCon.Warning("VIF Path3 Resume on FBRST MSK = %x", vif1Regs.mskpath3);
167 gsInterrupt();
168 vif1Regs.mskpath3 = false;
169 gifRegs.stat.M3P = 0;
170 }
171
172 vif1Regs.mskpath3 = false;
173 gifRegs.stat.M3P = 0;
174 vif1Regs.err.reset();
175 vif1.inprogress = 0;
176 vif1.cmd = 0;
177 vif1.vifstalled = false;
178 vif1Regs.stat.FQC = 0;
179 vif1Regs.stat.clear_flags(VIF1_STAT_FDR | VIF1_STAT_INT | VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS | VIF1_STAT_VPS);
180 }
181
182 /* Fixme: Forcebreaks are pretty unknown for operation, presumption is it just stops it what its doing
183 usually accompanied by a reset, but if we find a broken game which falls here, we need to see it! (Refraction) */
184
185 if (FBRST(value).FBK) // Forcebreak Vif.
186 {
187 /* I guess we should stop the VIF dma here, but not 100% sure (linuz) */
188 vif1Regs.stat.VFS = true;
189 vif1Regs.stat.VPS = VPS_IDLE;
190 cpuRegs.interrupt &= ~((1 << 1) | (1 << 10)); //Stop all vif1 DMA's
191 Console.WriteLn("vif1 force break");
192 }
193
194 if (FBRST(value).STP) // Stop Vif.
195 {
196 // Not completely sure about this, can't remember what game used this, but 'draining' the VIF helped it, instead of
197 // just stoppin the VIF (linuz).
198 vif1Regs.stat.VSS = true;
199 vif1Regs.stat.VPS = VPS_IDLE;
200 cpuRegs.interrupt &= ~((1 << 1) | (1 << 10)); //Stop all vif1 DMA's
201 vif1.vifstalled = true;
202 }
203
204 if (FBRST(value).STC) // Cancel Vif Stall.
205 {
206 bool cancel = false;
207
208 /* Cancel stall, first check if there is a stall to cancel, and then clear VIF1_STAT VSS|VFS|VIS|INT|ER0|ER1 bits */
209 if (vif1Regs.stat.test(VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS))
210 {
211 cancel = true;
212 }
213
214 vif1Regs.stat.clear_flags(VIF1_STAT_VSS | VIF1_STAT_VFS | VIF1_STAT_VIS |
215 VIF1_STAT_INT | VIF1_STAT_ER0 | VIF1_STAT_ER1);
216
217 if (cancel)
218 {
219 if (vif1.vifstalled)
220 {
221 g_vifCycles = 0;
222 // loop necessary for spiderman
223 switch(dmacRegs.ctrl.MFD)
224 {
225 case MFD_VIF1:
226 //Console.WriteLn("MFIFO Stall");
227 if(vif1ch.chcr.STR == true) CPU_INT(DMAC_MFIFO_VIF, 0);
228 break;
229
230 case NO_MFD:
231 case MFD_RESERVED:
232 case MFD_GIF: // Wonder if this should be with VIF?
233 // Gets the timing right - Flatout
234 if(vif1ch.chcr.STR == true) CPU_INT(DMAC_VIF1, 0);
235 break;
236 }
237
238 //vif1ch.chcr.STR = true;
239 }
240 }
241 }
242 }
243
244 __fi void vif1STAT(u32 value) {
245 VIF_LOG("VIF1_STAT write32 0x%8.8x", value);
246
247 /* Only FDR bit is writable, so mask the rest */
248 if ((vif1Regs.stat.FDR) ^ ((tVIF_STAT&)value).FDR) {
249 // different so can't be stalled
250 if (vif1Regs.stat.test(VIF1_STAT_INT | VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS)) {
251 DevCon.WriteLn("changing dir when vif1 fifo stalled");
252 }
253 }
254
255 vif1Regs.stat.FDR = VIF_STAT(value).FDR;
256
257 if (vif1Regs.stat.FDR) // Vif transferring to memory.
258 {
259 // Hack but it checks this is true before transfer? (fatal frame)
260 // Update Refraction: Use of this function has been investigated and understood.
261 // Before this ever happens, a DIRECT/HL command takes place sending the transfer info to the GS
262 // One of the registers told about this is TRXREG which tells us how much data is going to transfer (th x tw) in words
263 // As far as the GS is concerned, the transfer starts as soon as TRXDIR is accessed, which is why fatal frame
264 // was expecting data, the GS should already be sending it over (buffering in the FIFO)
265
266 vif1Regs.stat.FQC = min((u32)16, vif1.GSLastDownloadSize);
267 //Console.Warning("Reversing VIF Transfer for %x QWC", vif1.GSLastDownloadSize);
268
269 }
270 else // Memory transferring to Vif.
271 {
272 //Sometimes the value from the GS is bigger than vif wanted, so it just sets it back and cancels it.
273 //Other times it can read it off ;)
274 vif1Regs.stat.FQC = 0;
275 }
276 }
277
278 #define caseVif(x) (idx ? VIF1_##x : VIF0_##x)
279
280 // returns FALSE if no writeback is needed (or writeback is handled internally)
281 // returns TRUE if the caller should writeback the value to the eeHw register map.
282 _vifT __fi bool vifWrite32(u32 mem, u32 value) {
283 switch (mem) {
284 case caseVif(MARK):
285 VIF_LOG("VIF%d_MARK write32 0x%8.8x", idx, value);
286 vifXRegs.stat.MRK = false;
287 //vifXRegs.mark = value;
288 break;
289
290 case caseVif(FBRST):
291 if (!idx) vif0FBRST(value);
292 else vif1FBRST(value);
293 return false;
294
295 case caseVif(STAT):
296 if (idx) { // Only Vif1 does this stuff?
297 vif1STAT(value);
298 }
299 return false;
300
301 case caseVif(ERR):
302 case caseVif(MODE):
303 // standard register writes -- handled by caller.
304 break;
305
306 case caseVif(ROW0):
307 case caseVif(ROW1):
308 case caseVif(ROW2):
309 case caseVif(ROW3):
310 // Here's a neat way to obfuscate code. This is a super-fancy-complicated version
311 // of a standard psHu32(mem) = value; writeback. Handled by caller for us, thanks! --air
312 //if (!idx) g_vifmask.Row0[ (mem>>4)&3 ] = value;
313 //else g_vifmask.Row1[ (mem>>4)&3 ] = value;
314 //((u32*)&vifXRegs.r0) [((mem>>4)&3)*4] = value;
315 break;
316
317 case caseVif(COL0):
318 case caseVif(COL1):
319 case caseVif(COL2):
320 case caseVif(COL3):
321 // Here's a neat way to obfuscate code. This is a super-fancy-complicated version
322 // of a standard psHu32(mem) = value; writeback. Handled by caller for us, thanks! --air
323 //if (!idx) g_vifmask.Col0[ (mem>>4)&3 ] = value;
324 //else g_vifmask.Col1[ (mem>>4)&3 ] = value;
325 //((u32*)&vifXRegs.c0) [((mem>>4)&3)*4] = value;
326 break;
327 }
328
329 // fall-through case: issue standard writeback behavior.
330 return true;
331 }
332
333
334 template bool vifWrite32<0>(u32 mem, u32 value);
335 template bool vifWrite32<1>(u32 mem, u32 value);

  ViewVC Help
Powered by ViewVC 1.1.22