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

Contents of /trunk/pcsx2/Vif_Unpack.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: 10896 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
21 enum UnpackOffset {
22 OFFSET_X = 0,
23 OFFSET_Y = 1,
24 OFFSET_Z = 2,
25 OFFSET_W = 3
26 };
27
28 static __fi u32 setVifRowRegs(u32 reg, u32 data) {
29 switch (reg) {
30 case 0: vifRegs->r0 = data; break;
31 case 1: vifRegs->r1 = data; break;
32 case 2: vifRegs->r2 = data; break;
33 case 3: vifRegs->r3 = data; break;
34 jNO_DEFAULT;
35 }
36 return data;
37 }
38
39 static __fi u32 getVifRowRegs(u32 reg) {
40 switch (reg) {
41 case 0: return vifRegs->r0; break;
42 case 1: return vifRegs->r1; break;
43 case 2: return vifRegs->r2; break;
44 case 3: return vifRegs->r3; break;
45 jNO_DEFAULT;
46 }
47 return 0; // unreachable...
48 }
49
50 static __fi u32 getVifColRegs(u32 reg) {
51 switch (reg) {
52 case 0: return vifRegs->c0; break;
53 case 1: return vifRegs->c1; break;
54 case 2: return vifRegs->c2; break;
55 default: return vifRegs->c3; break;
56 }
57 return 0; // unreachable...
58 }
59
60 template< bool doMask >
61 static __ri void writeXYZW(u32 offnum, u32 &dest, u32 data) {
62 u32 vifRowReg = getVifRowRegs(offnum);
63 int n = 0;
64
65 if (doMask) {
66 switch (vif->cl) {
67 case 0: n = (vifRegs->mask >> (offnum * 2)) & 0x3; break;
68 case 1: n = (vifRegs->mask >> ( 8 + (offnum * 2))) & 0x3; break;
69 case 2: n = (vifRegs->mask >> (16 + (offnum * 2))) & 0x3; break;
70 default: n = (vifRegs->mask >> (24 + (offnum * 2))) & 0x3; break;
71 }
72 }
73
74 switch (n) {
75 case 0:
76 if ((vif->cmd & 0x6F) != 0x6f) {
77 switch (vifRegs->mode) {
78 case 1: dest = data + vifRowReg; break;
79 case 2: dest = setVifRowRegs(offnum, vifRowReg + data); break;
80 default: dest = data; break;
81 }
82 }
83 else dest = data; // v4-5 Unpack Mode
84 break;
85 case 1: dest = vifRowReg; break;
86 case 2: dest = getVifColRegs(vif->cl); break;
87 case 3: break;
88 }
89 }
90
91 template < bool doMask, class T >
92 static __fi void __fastcall UNPACK_S(u32 *dest, const T *data, int size)
93 {
94 //S-# will always be a complete packet, no matter what. So we can skip the offset bits
95 writeXYZW<doMask>(OFFSET_X, *dest++, *data);
96 writeXYZW<doMask>(OFFSET_Y, *dest++, *data);
97 writeXYZW<doMask>(OFFSET_Z, *dest++, *data);
98 writeXYZW<doMask>(OFFSET_W, *dest , *data);
99 }
100
101 template <bool doMask, class T>
102 static __ri void __fastcall UNPACK_V2(u32 *dest, const T *data, int size)
103 {
104 if (vifRegs->offset == OFFSET_X)
105 {
106 if (size > 0)
107 {
108 writeXYZW<doMask>(vifRegs->offset, *dest++, *data++);
109 vifRegs->offset = OFFSET_Y;
110 size--;
111 }
112 }
113
114 if (vifRegs->offset == OFFSET_Y)
115 {
116 if (size > 0)
117 {
118 writeXYZW<doMask>(vifRegs->offset, *dest++, *data);
119 vifRegs->offset = OFFSET_Z;
120 size--;
121 }
122 }
123
124 if (vifRegs->offset == OFFSET_Z)
125 {
126 writeXYZW<doMask>(vifRegs->offset, *dest++, *dest-2);
127 vifRegs->offset = OFFSET_W;
128 }
129
130 if (vifRegs->offset == OFFSET_W)
131 {
132 writeXYZW<doMask>(vifRegs->offset, *dest, *data);
133 vifRegs->offset = OFFSET_X;
134 }
135 }
136
137 template <bool doMask, class T>
138 static __ri void __fastcall UNPACK_V3(u32 *dest, const T *data, int size)
139 {
140 if(vifRegs->offset == OFFSET_X)
141 {
142 if (size > 0)
143 {
144 writeXYZW<doMask>(vifRegs->offset, *dest++, *data++);
145 vifRegs->offset = OFFSET_Y;
146 size--;
147 }
148 }
149
150 if(vifRegs->offset == OFFSET_Y)
151 {
152 if (size > 0)
153 {
154 writeXYZW<doMask>(vifRegs->offset, *dest++, *data++);
155 vifRegs->offset = OFFSET_Z;
156 size--;
157 }
158 }
159
160 if(vifRegs->offset == OFFSET_Z)
161 {
162 if (size > 0)
163 {
164 writeXYZW<doMask>(vifRegs->offset, *dest++, *data++);
165 vifRegs->offset = OFFSET_W;
166 size--;
167 }
168 }
169
170 if(vifRegs->offset == OFFSET_W)
171 {
172 // V3-# does some bizarre thing with alignment, every 6qw of data the W becomes 0 (strange console!)
173 // Ape Escape doesn't seem to like it tho (what the hell?) gonna have to investigate
174 writeXYZW<doMask>(vifRegs->offset, *dest, *data);
175 vifRegs->offset = OFFSET_X;
176 }
177 }
178
179 template <bool doMask, class T>
180 static __fi void __fastcall UNPACK_V4(u32 *dest, const T *data , int size)
181 {
182 while (size > 0)
183 {
184 writeXYZW<doMask>(vifRegs->offset, *dest++, *data++);
185 vifRegs->offset++;
186 size--;
187 }
188
189 if (vifRegs->offset > OFFSET_W) vifRegs->offset = OFFSET_X;
190 }
191
192 template< bool doMask >
193 static __ri void __fastcall UNPACK_V4_5(u32 *dest, const u32 *data, int size)
194 {
195 //As with S-#, this will always be a complete packet
196 writeXYZW<doMask>(OFFSET_X, *dest++, ((*data & 0x001f) << 3));
197 writeXYZW<doMask>(OFFSET_Y, *dest++, ((*data & 0x03e0) >> 2));
198 writeXYZW<doMask>(OFFSET_Z, *dest++, ((*data & 0x7c00) >> 7));
199 writeXYZW<doMask>(OFFSET_W, *dest, ((*data & 0x8000) >> 8));
200 }
201
202 // =====================================================================================================
203
204 template < bool doMask, int size, class T >
205 static void __fastcall fUNPACK_S(u32 *dest, const T *data)
206 {
207 UNPACK_S<doMask>( dest, data, size );
208 }
209
210 template <bool doMask, int size, class T>
211 static void __fastcall fUNPACK_V2(u32 *dest, const T *data)
212 {
213 UNPACK_V2<doMask>( dest, data, size );
214 }
215
216 template <bool doMask, int size, class T>
217 static void __fastcall fUNPACK_V3(u32 *dest, const T *data)
218 {
219 UNPACK_V3<doMask>( dest, data, size );
220 }
221
222 template <bool doMask, int size, class T>
223 static void __fastcall fUNPACK_V4(u32 *dest, const T *data)
224 {
225 UNPACK_V4<doMask>( dest, data, size );
226 }
227
228 template< bool doMask >
229 static void __fastcall fUNPACK_V4_5(u32 *dest, const u32 *data)
230 {
231 UNPACK_V4_5<doMask>(dest, data, 0); // size is ignored.
232 }
233
234 // --------------------------------------------------------------------------------------
235 // Main table for function unpacking.
236 // --------------------------------------------------------------------------------------
237 // The extra data bsize/dsize/etc are all duplicated between the doMask enabled and
238 // disabled versions. This is probably simpler and more efficient than bothering
239 // to generate separate tables.
240 //
241 // The double-cast function pointer nonsense is to appease GCC, which gives some rather
242 // cryptic error about being unable to deduce the type parameters (I think it's a bug
243 // relating to __fastcall, which I recall having some other places as well). It's fixed
244 // by explicitly casting the function to itself prior to casting it to what we need it
245 // to be cast as. --air
246 //
247
248 #define _upk (UNPACKFUNCTYPE)
249 #define _odd (UNPACKFUNCTYPE_ODD)
250 #define _unpk_s(bits) (UNPACKFUNCTYPE_S##bits)
251 #define _odd_s(bits) (UNPACKFUNCTYPE_ODD_S##bits)
252 #define _unpk_u(bits) (UNPACKFUNCTYPE_U##bits)
253 #define _odd_u(bits) (UNPACKFUNCTYPE_ODD_U##bits)
254
255 // 32-bits versions are unsigned-only!!
256 #define UnpackFuncPair32( sizefac, vt, doMask ) \
257 (UNPACKFUNCTYPE)_unpk_u(32) fUNPACK_##vt<doMask, sizefac, u32>, \
258 (UNPACKFUNCTYPE)_unpk_u(32) fUNPACK_##vt<doMask, sizefac, u32>, \
259 (UNPACKFUNCTYPE_ODD)_odd_u(32) UNPACK_##vt<doMask, u32>, \
260 (UNPACKFUNCTYPE_ODD)_odd_u(32) UNPACK_##vt<doMask, u32>,
261
262 #define UnpackFuncPair( sizefac, vt, bits, doMask ) \
263 (UNPACKFUNCTYPE)_unpk_u(bits) fUNPACK_##vt<doMask, sizefac, u##bits>, \
264 (UNPACKFUNCTYPE)_unpk_s(bits) fUNPACK_##vt<doMask, sizefac, s##bits>, \
265 (UNPACKFUNCTYPE_ODD)_odd_u(bits) UNPACK_##vt<doMask, u##bits>, \
266 (UNPACKFUNCTYPE_ODD)_odd_s(bits) UNPACK_##vt<doMask, s##bits>,
267
268 #define UnpackFuncSet( doMask ) \
269 { UnpackFuncPair32( 4, S, doMask ) 1, 4, 4, 4 }, /* 0x0 - S-32 */ \
270 { UnpackFuncPair ( 4, S, 16, doMask ) 2, 2, 2, 4 }, /* 0x1 - S-16 */ \
271 { UnpackFuncPair ( 4, S, 8, doMask ) 4, 1, 1, 4 }, /* 0x2 - S-8 */ \
272 { NULL, NULL, NULL, NULL, 0, 0, 0, 0 }, /* 0x3 (NULL) */ \
273 { UnpackFuncPair32( 2, V2, doMask ) 24, 4, 8, 2 }, /* 0x4 - V2-32 */ \
274 { UnpackFuncPair ( 2, V2, 16, doMask ) 12, 2, 4, 2 }, /* 0x5 - V2-16 */ \
275 { UnpackFuncPair ( 2, V2, 8, doMask ) 6, 1, 2, 2 }, /* 0x6 - V2-8 */ \
276 { NULL, NULL, NULL, NULL,0, 0, 0, 0 }, /* 0x7 (NULL) */ \
277 { UnpackFuncPair32( 3, V3, doMask ) 36, 4, 12, 3 }, /* 0x8 - V3-32 */ \
278 { UnpackFuncPair ( 3, V3, 16, doMask ) 18, 2, 6, 3 }, /* 0x9 - V3-16 */ \
279 { UnpackFuncPair ( 3, V3, 8, doMask ) 9, 1, 3, 3 }, /* 0xA - V3-8 */ \
280 { NULL, NULL, NULL, NULL,0, 0, 0, 0 }, /* 0xB (NULL) */ \
281 { UnpackFuncPair32( 4, V4, doMask ) 48, 4, 16, 4 }, /* 0xC - V4-32 */ \
282 { UnpackFuncPair ( 4, V4, 16, doMask ) 24, 2, 8, 4 }, /* 0xD - V4-16 */ \
283 { UnpackFuncPair ( 4, V4, 8, doMask ) 12, 1, 4, 4 }, /* 0xE - V4-8 */ \
284 { /* 0xF - V4-5 */ \
285 (UNPACKFUNCTYPE)_unpk_u(32) fUNPACK_V4_5<doMask>, \
286 (UNPACKFUNCTYPE)_unpk_u(32) fUNPACK_V4_5<doMask>, \
287 (UNPACKFUNCTYPE_ODD)_odd_u(32) UNPACK_V4_5<doMask>, \
288 (UNPACKFUNCTYPE_ODD)_odd_u(32) UNPACK_V4_5<doMask>, \
289 6, 2, 2, 4 },
290
291 const __aligned16 VIFUnpackFuncTable VIFfuncTable[32] =
292 {
293 UnpackFuncSet( false )
294 UnpackFuncSet( true )
295 };
296
297 //----------------------------------------------------------------------------
298 // Unpack Setup Code
299 //----------------------------------------------------------------------------
300
301 _vifT void vifUnpackSetup(const u32 *data) {
302
303 vifStruct& vifX = GetVifX;
304
305 if ((vifXRegs.cycle.wl == 0) && (vifXRegs.cycle.wl < vifXRegs.cycle.cl)) {
306 Console.WriteLn("Vif%d CL %d, WL %d", idx, vifXRegs.cycle.cl, vifXRegs.cycle.wl);
307 vifX.cmd = 0;
308 return; // Skipping write and 0 write-cycles, so do nothing!
309 }
310
311
312 //if (!idx) vif0FLUSH(); // Only VU0?
313
314 vifX.usn = (vifXRegs.code >> 14) & 0x01;
315 int vifNum = (vifXRegs.code >> 16) & 0xff;
316
317 if (vifNum == 0) vifNum = 256;
318 vifXRegs.num = vifNum;
319
320 if (vifXRegs.cycle.wl <= vifXRegs.cycle.cl) {
321 if (!idx) vif0.tag.size = ((vifNum * VIFfuncTable[ vif0.cmd & 0xf ].gsize) + 3) >> 2;
322 else vif1.tag.size = ((vifNum * VIFfuncTable[ vif1.cmd & 0xf ].gsize) + 3) >> 2;
323 }
324 else {
325 int n = vifXRegs.cycle.cl * (vifNum / vifXRegs.cycle.wl) +
326 _limit(vifNum % vifXRegs.cycle.wl, vifXRegs.cycle.cl);
327
328 if (!idx) vif0.tag.size = ((n * VIFfuncTable[ vif0.cmd & 0xf ].gsize) + 3) >> 2;
329 else vif1.tag.size = ((n * VIFfuncTable[ vif1.cmd & 0xf ].gsize) + 3) >> 2;
330 }
331
332 u32 addr = vifXRegs.code;
333 if (idx && ((addr>>15)&1)) addr += vif1Regs.tops;
334 vifX.tag.addr = (addr<<4) & (idx ? 0x3ff0 : 0xff0);
335
336 VIF_LOG("Unpack VIF%x, QWC %x tagsize %x", idx, vifNum, vif0.tag.size);
337
338 vifX.cl = 0;
339 vifX.tag.cmd = vifX.cmd;
340 vifXRegs.offset = 0;
341 }
342
343 template void vifUnpackSetup<0>(const u32 *data);
344 template void vifUnpackSetup<1>(const u32 *data);

  ViewVC Help
Powered by ViewVC 1.1.22