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

  ViewVC Help
Powered by ViewVC 1.1.22