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

Annotation of /trunk/pcsx2/IPU/IPU.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 280 - (hide annotations) (download)
Thu Dec 23 12:02:12 2010 UTC (9 years, 6 months ago) by william
File size: 23384 byte(s)
re-commit (had local access denied errors when committing)
1 william 31 /* 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    
19     #include "IPU.h"
20 william 62 #include "IPUdma.h"
21 william 31 #include "yuv2rgb.h"
22 william 62 #include "mpeg2lib/Mpeg.h"
23    
24 william 31 #include "Vif.h"
25     #include "Gif.h"
26     #include "Vif_Dma.h"
27 william 62 #include <limits.h>
28 william 31
29 william 280 #include "Utilities/MemsetFast.inl"
30    
31 william 31 // the BP doesn't advance and returns -1 if there is no data to be read
32 william 273 __aligned16 tIPU_cmd ipu_cmd;
33 william 62 __aligned16 tIPU_BP g_BP;
34 william 273 __aligned16 decoder_t decoder;
35 william 31
36     void IPUWorker();
37    
38     // Color conversion stuff, the memory layout is a total hack
39     // convert_data_buffer is a pointer to the internal rgb struct (the first param in convert_init_t)
40     //char convert_data_buffer[sizeof(convert_rgb_t)];
41 william 62 //char convert_data_buffer[0x1C]; // unused?
42     //u8 PCT[] = {'r', 'I', 'P', 'B', 'D', '-', '-', '-'}; // unused?
43 william 31
44     // Quantization matrix
45 william 62 static u16 vqclut[16]; //clut conversion table
46     static u8 s_thresh[2]; //thresholds for color conversions
47 william 31 int coded_block_pattern = 0;
48    
49 william 62
50 william 31 u8 indx4[16*16/2];
51    
52 william 273
53     void tIPU_cmd::clear()
54     {
55     memzero_sse_a(*this);
56     current = 0xffffffff;
57     }
58    
59 william 62 __fi void IPUProcessInterrupt()
60 william 31 {
61 william 273 if (ipuRegs.ctrl.BUSY) // && (g_BP.FP || g_BP.IFC || (ipu1dma.chcr.STR && ipu1dma.qwc > 0)))
62     IPUWorker();
63 william 31 }
64    
65     /////////////////////////////////////////////////////////
66     // Register accesses (run on EE thread)
67     int ipuInit()
68     {
69 william 62 memzero(ipuRegs);
70 william 31 memzero(g_BP);
71 william 62 memzero(decoder);
72    
73     decoder.picture_structure = FRAME_PICTURE; //default: progressive...my guess:P
74    
75 william 31 ipu_fifo.init();
76     ipu_cmd.clear();
77 william 62
78 william 31 return 0;
79     }
80    
81     void ipuReset()
82     {
83     ipuInit();
84     }
85    
86     void ReportIPU()
87     {
88 william 62 //Console.WriteLn(g_nDMATransfer.desc());
89 william 31 Console.WriteLn(ipu_fifo.in.desc());
90     Console.WriteLn(ipu_fifo.out.desc());
91     Console.WriteLn(g_BP.desc());
92     Console.WriteLn("vqclut = 0x%x.", vqclut);
93     Console.WriteLn("s_thresh = 0x%x.", s_thresh);
94     Console.WriteLn("coded_block_pattern = 0x%x.", coded_block_pattern);
95 william 62 Console.WriteLn("g_decoder = 0x%x.", &decoder);
96     Console.WriteLn("mpeg2_scan = 0x%x.", &mpeg2_scan);
97 william 31 Console.WriteLn(ipu_cmd.desc());
98     Console.Newline();
99     }
100    
101     void SaveStateBase::ipuFreeze()
102     {
103     // Get a report of the status of the ipu variables when saving and loading savestates.
104     //ReportIPU();
105     FreezeTag("IPU");
106     Freeze(ipu_fifo);
107    
108     Freeze(g_BP);
109     Freeze(vqclut);
110     Freeze(s_thresh);
111     Freeze(coded_block_pattern);
112 william 62 Freeze(decoder);
113 william 31 Freeze(ipu_cmd);
114     }
115    
116 william 62 void tIPU_CMD_IDEC::log() const
117 william 31 {
118 william 62 IPU_LOG("IDEC command.");
119    
120     if (FB) IPU_LOG(" Skip %d bits.", FB);
121     IPU_LOG(" Quantizer step code=0x%X.", QSC);
122    
123     if (DTD == 0)
124     IPU_LOG(" Does not decode DT.");
125     else
126     IPU_LOG(" Decodes DT.");
127    
128     if (SGN == 0)
129     IPU_LOG(" No bias.");
130     else
131     IPU_LOG(" Bias=128.");
132    
133     if (DTE == 1) IPU_LOG(" Dither Enabled.");
134     if (OFM == 0)
135     IPU_LOG(" Output format is RGB32.");
136     else
137     IPU_LOG(" Output format is RGB16.");
138    
139     IPU_LOG("");
140 william 31 }
141    
142 william 62 void tIPU_CMD_BDEC::log(int s_bdec) const
143 william 31 {
144 william 62 IPU_LOG("BDEC(macroblock decode) command %x, num: 0x%x", cpuRegs.pc, s_bdec);
145     if (FB) IPU_LOG(" Skip 0x%X bits.", FB);
146    
147     if (MBI)
148     IPU_LOG(" Intra MB.");
149     else
150     IPU_LOG(" Non-intra MB.");
151    
152     if (DCR)
153     IPU_LOG(" Resets DC prediction value.");
154     else
155     IPU_LOG(" Doesn't reset DC prediction value.");
156    
157     if (DT)
158     IPU_LOG(" Use field DCT.");
159     else
160     IPU_LOG(" Use frame DCT.");
161    
162     IPU_LOG(" Quantizer step=0x%X", QSC);
163     }
164    
165     void tIPU_CMD_CSC::log_from_YCbCr() const
166     {
167     IPU_LOG("CSC(Colorspace conversion from YCbCr) command (%d).", MBC);
168     if (OFM)
169     IPU_LOG("Output format is RGB16. ");
170     else
171     IPU_LOG("Output format is RGB32. ");
172    
173     if (DTE) IPU_LOG("Dithering enabled.");
174     }
175    
176     void tIPU_CMD_CSC::log_from_RGB32() const
177     {
178     IPU_LOG("PACK (Colorspace conversion from RGB32) command.");
179    
180     if (OFM)
181     IPU_LOG("Output format is RGB16. ");
182     else
183     IPU_LOG("Output format is INDX4. ");
184    
185     if (DTE) IPU_LOG("Dithering enabled.");
186    
187     IPU_LOG("Number of macroblocks to be converted: %d", MBC);
188     }
189    
190    
191     __fi u32 ipuRead32(u32 mem)
192     {
193 william 31 // Note: It's assumed that mem's input value is always in the 0x10002000 page
194     // of memory (if not, it's probably bad code).
195    
196     pxAssert((mem & ~0xff) == 0x10002000);
197     mem &= 0xff; // ipu repeats every 0x100
198    
199 william 273 IPUProcessInterrupt();
200 william 31
201     switch (mem)
202     {
203     ipucase(IPU_CTRL): // IPU_CTRL
204 william 191 {
205 william 62 ipuRegs.ctrl.IFC = g_BP.IFC;
206     ipuRegs.ctrl.CBP = coded_block_pattern;
207 william 31
208 william 62 if (!ipuRegs.ctrl.BUSY)
209     IPU_LOG("read32: IPU_CTRL=0x%08X", ipuRegs.ctrl._u32);
210 william 31
211 william 191 return ipuRegs.ctrl._u32;
212 william 273 }
213 william 31
214     ipucase(IPU_BP): // IPU_BP
215 william 191 {
216     pxAssume(g_BP.FP <= 2);
217    
218 william 62 ipuRegs.ipubp = g_BP.BP & 0x7f;
219     ipuRegs.ipubp |= g_BP.IFC << 8;
220 william 191 ipuRegs.ipubp |= g_BP.FP << 16;
221 william 31
222 william 62 IPU_LOG("read32: IPU_BP=0x%08X", ipuRegs.ipubp);
223 william 191 return ipuRegs.ipubp;
224     }
225 william 62
226 william 31 default:
227 william 62 IPU_LOG("read32: Addr=0x%08X Value = 0x%08X", mem, psHu32(IPU_CMD + mem));
228 william 31 }
229    
230 william 62 return psHu32(IPU_CMD + mem);
231 william 31 }
232    
233 william 62 __fi u64 ipuRead64(u32 mem)
234 william 31 {
235     // Note: It's assumed that mem's input value is always in the 0x10002000 page
236     // of memory (if not, it's probably bad code).
237    
238     pxAssert((mem & ~0xff) == 0x10002000);
239     mem &= 0xff; // ipu repeats every 0x100
240    
241 william 273 IPUProcessInterrupt();
242 william 31
243     switch (mem)
244     {
245     ipucase(IPU_CMD): // IPU_CMD
246 william 62 if (ipuRegs.cmd.DATA & 0xffffff)
247     IPU_LOG("read64: IPU_CMD=BUSY=%x, DATA=%08X", ipuRegs.cmd.BUSY ? 1 : 0, ipuRegs.cmd.DATA);
248 william 31 break;
249    
250     ipucase(IPU_CTRL):
251     DevCon.Warning("reading 64bit IPU ctrl");
252     break;
253    
254     ipucase(IPU_BP):
255     DevCon.Warning("reading 64bit IPU top");
256     break;
257    
258     ipucase(IPU_TOP): // IPU_TOP
259 william 62 IPU_LOG("read64: IPU_TOP=%x, bp = %d", ipuRegs.top, g_BP.BP);
260 william 31 break;
261    
262     default:
263 william 62 IPU_LOG("read64: Unknown=%x", mem);
264 william 31 break;
265     }
266 william 62 return psHu64(IPU_CMD + mem);
267 william 31 }
268    
269     void ipuSoftReset()
270     {
271     ipu_fifo.clear();
272    
273     coded_block_pattern = 0;
274    
275 william 62 ipuRegs.ctrl.reset();
276     ipuRegs.top = 0;
277 william 31 ipu_cmd.clear();
278 william 62 ipuRegs.cmd.BUSY = 0;
279 william 31
280 william 191 memzero(g_BP);
281 william 31 }
282    
283 william 62 __fi bool ipuWrite32(u32 mem, u32 value)
284 william 31 {
285     // Note: It's assumed that mem's input value is always in the 0x10002000 page
286     // of memory (if not, it's probably bad code).
287    
288     pxAssert((mem & ~0xfff) == 0x10002000);
289     mem &= 0xfff;
290    
291     switch (mem)
292     {
293     ipucase(IPU_CMD): // IPU_CMD
294 william 62 IPU_LOG("write32: IPU_CMD=0x%08X", value);
295 william 31 IPUCMD_WRITE(value);
296 william 273 IPUProcessInterrupt();
297 william 62 return false;
298 william 31
299     ipucase(IPU_CTRL): // IPU_CTRL
300     // CTRL = the first 16 bits of ctrl [0x8000ffff], + value for the next 16 bits,
301     // minus the reserved bits. (18-19; 27-29) [0x47f30000]
302 william 62 ipuRegs.ctrl.write(value);
303     if (ipuRegs.ctrl.IDP == 3)
304 william 31 {
305     Console.WriteLn("IPU Invalid Intra DC Precision, switching to 9 bits");
306 william 62 ipuRegs.ctrl.IDP = 1;
307 william 31 }
308    
309 william 62 if (ipuRegs.ctrl.RST) ipuSoftReset(); // RESET
310 william 31
311 william 62 IPU_LOG("write32: IPU_CTRL=0x%08X", value);
312     return false;
313 william 31 }
314 william 62 return true;
315 william 31 }
316    
317 william 62 // returns FALSE when the writeback is handled, TRUE if the caller should do the
318     // writeback itself.
319     __fi bool ipuWrite64(u32 mem, u64 value)
320 william 31 {
321     // Note: It's assumed that mem's input value is always in the 0x10002000 page
322     // of memory (if not, it's probably bad code).
323    
324     pxAssert((mem & ~0xfff) == 0x10002000);
325     mem &= 0xfff;
326    
327     switch (mem)
328     {
329     ipucase(IPU_CMD):
330 william 62 IPU_LOG("write64: IPU_CMD=0x%08X", value);
331 william 31 IPUCMD_WRITE((u32)value);
332 william 273 IPUProcessInterrupt();
333 william 62 return false;
334     }
335 william 31
336 william 62 return true;
337 william 31 }
338    
339    
340     //////////////////////////////////////////////////////
341     // IPU Commands (exec on worker thread only)
342    
343     static void ipuBCLR(u32 val)
344     {
345     ipu_fifo.in.clear();
346    
347 william 191 memzero(g_BP);
348 william 31 g_BP.BP = val & 0x7F;
349 william 191
350 william 62 ipuRegs.ctrl.BUSY = 0;
351     ipuRegs.cmd.BUSY = 0;
352 william 31 IPU_LOG("Clear IPU input FIFO. Set Bit offset=0x%X", g_BP.BP);
353     }
354    
355 william 273 static __ri void ipuIDEC(tIPU_CMD_IDEC idec)
356 william 31 {
357 william 273 idec.log();
358 william 31
359     //from IPU_CTRL
360 william 273 ipuRegs.ctrl.PCT = I_TYPE; //Intra DECoding;)
361 william 31
362 william 273 decoder.coding_type = ipuRegs.ctrl.PCT;
363     decoder.mpeg1 = ipuRegs.ctrl.MP1;
364     decoder.q_scale_type = ipuRegs.ctrl.QST;
365     decoder.intra_vlc_format = ipuRegs.ctrl.IVF;
366     decoder.scantype = ipuRegs.ctrl.AS;
367     decoder.intra_dc_precision = ipuRegs.ctrl.IDP;
368 william 62
369 william 273 //from IDEC value
370     decoder.quantizer_scale = idec.QSC;
371     decoder.frame_pred_frame_dct= !idec.DTD;
372     decoder.sgn = idec.SGN;
373     decoder.dte = idec.DTE;
374     decoder.ofm = idec.OFM;
375 william 31
376     //other stuff
377 william 273 decoder.dcr = 1; // resets DC prediction value
378 william 31 }
379    
380     static int s_bdec = 0;
381    
382 william 273 static __ri void ipuBDEC(tIPU_CMD_BDEC bdec)
383 william 31 {
384 william 273 bdec.log(s_bdec);
385     if (IsDebugBuild) s_bdec++;
386 william 31
387 william 273 decoder.coding_type = I_TYPE;
388     decoder.mpeg1 = ipuRegs.ctrl.MP1;
389     decoder.q_scale_type = ipuRegs.ctrl.QST;
390     decoder.intra_vlc_format = ipuRegs.ctrl.IVF;
391     decoder.scantype = ipuRegs.ctrl.AS;
392     decoder.intra_dc_precision = ipuRegs.ctrl.IDP;
393 william 31
394     //from BDEC value
395 william 273 decoder.quantizer_scale = decoder.q_scale_type ? non_linear_quantizer_scale [bdec.QSC] : bdec.QSC << 1;
396     decoder.macroblock_modes = bdec.DT ? DCT_TYPE_INTERLACED : 0;
397     decoder.dcr = bdec.DCR;
398     decoder.macroblock_modes |= bdec.MBI ? MACROBLOCK_INTRA : MACROBLOCK_PATTERN;
399 william 31
400 william 273 memzero_sse_a(decoder.mb8);
401     memzero_sse_a(decoder.mb16);
402 william 31 }
403    
404 william 273 static __fi bool ipuVDEC(u32 val)
405 william 31 {
406     switch (ipu_cmd.pos[0])
407     {
408     case 0:
409 william 191 if (!bitstream_init()) return false;
410 william 31
411     switch ((val >> 26) & 3)
412     {
413     case 0://Macroblock Address Increment
414 william 62 decoder.mpeg1 = ipuRegs.ctrl.MP1;
415     ipuRegs.cmd.DATA = get_macroblock_address_increment();
416 william 31 break;
417    
418 william 62 case 1://Macroblock Type
419     decoder.frame_pred_frame_dct = 1;
420     decoder.coding_type = ipuRegs.ctrl.PCT;
421     ipuRegs.cmd.DATA = get_macroblock_modes();
422 william 31 break;
423    
424 william 62 case 2://Motion Code
425     ipuRegs.cmd.DATA = get_motion_delta(0);
426 william 31 break;
427    
428     case 3://DMVector
429 william 62 ipuRegs.cmd.DATA = get_dmv();
430 william 31 break;
431 william 191
432     jNO_DEFAULT
433 william 31 }
434    
435 william 273 // HACK ATTACK! This code OR's the MPEG decoder's bitstream position into the upper
436     // 16 bits of DATA; which really doesn't make sense since (a) we already rewound the bits
437     // back into the IPU internal buffer above, and (b) the IPU doesn't have an MPEG internal
438     // 32-bit decoder buffer of its own anyway. Furthermore, setting the upper 16 bits to
439     // any value other than zero appears to work fine. When set to zero, however, FMVs run
440     // very choppy (basically only decoding/updating every 30th frame or so). So yeah,
441     // someone with knowledge on the subject please feel free to explain this one. :) --air
442    
443 william 280 // The upper bits are the "length" of the decoded command, where the lower is the address.
444     // This is due to differences with IPU and the MPEG standard. See get_macroblock_address_increment().
445 william 31
446 william 62 ipuRegs.ctrl.ECD = (ipuRegs.cmd.DATA == 0);
447 william 31
448     case 1:
449 william 62 if (!getBits32((u8*)&ipuRegs.top, 0))
450 william 31 {
451     ipu_cmd.pos[0] = 1;
452 william 62 return false;
453 william 31 }
454    
455 william 191 ipuRegs.top = BigEndian(ipuRegs.top);
456 william 31
457 william 62 IPU_LOG("VDEC command data 0x%x(0x%x). Skip 0x%X bits/Table=%d (%s), pct %d",
458     ipuRegs.cmd.DATA, ipuRegs.cmd.DATA >> 16, val & 0x3f, (val >> 26) & 3, (val >> 26) & 1 ?
459     ((val >> 26) & 2 ? "DMV" : "MBT") : (((val >> 26) & 2 ? "MC" : "MBAI")), ipuRegs.ctrl.PCT);
460 william 273
461 william 62 return true;
462 william 31
463 william 191 jNO_DEFAULT
464 william 31 }
465    
466 william 62 return false;
467 william 31 }
468    
469 william 273 static __ri bool ipuFDEC(u32 val)
470 william 31 {
471 william 62 if (!getBits32((u8*)&ipuRegs.cmd.DATA, 0)) return false;
472 william 31
473 william 191 ipuRegs.cmd.DATA = BigEndian(ipuRegs.cmd.DATA);
474 william 62 ipuRegs.top = ipuRegs.cmd.DATA;
475 william 31
476 william 62 IPU_LOG("FDEC read: 0x%08x", ipuRegs.top);
477 william 31
478 william 62 return true;
479 william 31 }
480    
481 william 62 static bool ipuSETIQ(u32 val)
482 william 31 {
483     if ((val >> 27) & 1)
484     {
485 william 62 u8 (&niq)[64] = decoder.niq;
486 william 31
487 william 62 for(;ipu_cmd.pos[0] < 8; ipu_cmd.pos[0]++)
488     {
489     if (!getBits64((u8*)niq + 8 * ipu_cmd.pos[0], 1)) return false;
490     }
491    
492     IPU_LOG("Read non-intra quantization matrix from FIFO.");
493 william 273 for (uint i = 0; i < 8; i++)
494 william 31 {
495     IPU_LOG("%02X %02X %02X %02X %02X %02X %02X %02X",
496     niq[i * 8 + 0], niq[i * 8 + 1], niq[i * 8 + 2], niq[i * 8 + 3],
497     niq[i * 8 + 4], niq[i * 8 + 5], niq[i * 8 + 6], niq[i * 8 + 7]);
498     }
499     }
500     else
501     {
502 william 62 u8 (&iq)[64] = decoder.iq;
503 william 31
504 william 62 for(;ipu_cmd.pos[0] < 8; ipu_cmd.pos[0]++)
505     {
506     if (!getBits64((u8*)iq + 8 * ipu_cmd.pos[0], 1)) return false;
507     }
508    
509     IPU_LOG("Read intra quantization matrix from FIFO.");
510 william 273 for (uint i = 0; i < 8; i++)
511 william 31 {
512     IPU_LOG("%02X %02X %02X %02X %02X %02X %02X %02X",
513     iq[i * 8 + 0], iq[i * 8 + 1], iq[i * 8 + 2], iq[i *8 + 3],
514     iq[i * 8 + 4], iq[i * 8 + 5], iq[i * 8 + 6], iq[i *8 + 7]);
515     }
516     }
517    
518 william 62 return true;
519 william 31 }
520    
521 william 62 static bool ipuSETVQ(u32 val)
522 william 31 {
523 william 62 for(;ipu_cmd.pos[0] < 4; ipu_cmd.pos[0]++)
524 william 31 {
525 william 62 if (!getBits64(((u8*)vqclut) + 8 * ipu_cmd.pos[0], 1)) return false;
526 william 31 }
527    
528 william 191 IPU_LOG("SETVQ command. Read VQCLUT table from FIFO.\n"
529     "%02d:%02d:%02d %02d:%02d:%02d %02d:%02d:%02d %02d:%02d:%02d\n"
530     "%02d:%02d:%02d %02d:%02d:%02d %02d:%02d:%02d %02d:%02d:%02d\n"
531     "%02d:%02d:%02d %02d:%02d:%02d %02d:%02d:%02d %02d:%02d:%02d\n"
532 william 273 "%02d:%02d:%02d %02d:%02d:%02d %02d:%02d:%02d %02d:%02d:%02d",
533 william 62 vqclut[0] >> 10, (vqclut[0] >> 5) & 0x1F, vqclut[0] & 0x1F,
534     vqclut[1] >> 10, (vqclut[1] >> 5) & 0x1F, vqclut[1] & 0x1F,
535     vqclut[2] >> 10, (vqclut[2] >> 5) & 0x1F, vqclut[2] & 0x1F,
536     vqclut[3] >> 10, (vqclut[3] >> 5) & 0x1F, vqclut[3] & 0x1F,
537     vqclut[4] >> 10, (vqclut[4] >> 5) & 0x1F, vqclut[4] & 0x1F,
538     vqclut[5] >> 10, (vqclut[5] >> 5) & 0x1F, vqclut[5] & 0x1F,
539     vqclut[6] >> 10, (vqclut[6] >> 5) & 0x1F, vqclut[6] & 0x1F,
540     vqclut[7] >> 10, (vqclut[7] >> 5) & 0x1F, vqclut[7] & 0x1F,
541     vqclut[8] >> 10, (vqclut[8] >> 5) & 0x1F, vqclut[8] & 0x1F,
542     vqclut[9] >> 10, (vqclut[9] >> 5) & 0x1F, vqclut[9] & 0x1F,
543     vqclut[10] >> 10, (vqclut[10] >> 5) & 0x1F, vqclut[10] & 0x1F,
544     vqclut[11] >> 10, (vqclut[11] >> 5) & 0x1F, vqclut[11] & 0x1F,
545     vqclut[12] >> 10, (vqclut[12] >> 5) & 0x1F, vqclut[12] & 0x1F,
546     vqclut[13] >> 10, (vqclut[13] >> 5) & 0x1F, vqclut[13] & 0x1F,
547     vqclut[14] >> 10, (vqclut[14] >> 5) & 0x1F, vqclut[14] & 0x1F,
548     vqclut[15] >> 10, (vqclut[15] >> 5) & 0x1F, vqclut[15] & 0x1F);
549    
550     return true;
551 william 31 }
552    
553     // IPU Transfers are split into 8Qwords so we need to send ALL the data
554 william 273 static __ri bool ipuCSC(tIPU_CMD_CSC csc)
555 william 31 {
556     csc.log_from_YCbCr();
557    
558     for (;ipu_cmd.index < (int)csc.MBC; ipu_cmd.index++)
559     {
560 william 62 for(;ipu_cmd.pos[0] < 48; ipu_cmd.pos[0]++)
561 william 31 {
562 william 62 if (!getBits64((u8*)&decoder.mb8 + 8 * ipu_cmd.pos[0], 1)) return false;
563 william 31 }
564    
565 william 62 ipu_csc(decoder.mb8, decoder.rgb32, 0);
566     if (csc.OFM) ipu_dither(decoder.rgb32, decoder.rgb16, csc.DTE);
567    
568 william 31 if (csc.OFM)
569     {
570 william 273 ipu_cmd.pos[1] += ipu_fifo.out.write(((u32*) & decoder.rgb16) + 4 * ipu_cmd.pos[1], 32 - ipu_cmd.pos[1]);
571     if (ipu_cmd.pos[1] < 32) return false;
572 william 31 }
573     else
574     {
575 william 273 ipu_cmd.pos[1] += ipu_fifo.out.write(((u32*) & decoder.rgb32) + 4 * ipu_cmd.pos[1], 64 - ipu_cmd.pos[1]);
576     if (ipu_cmd.pos[1] < 64) return false;
577 william 31 }
578    
579     ipu_cmd.pos[0] = 0;
580     ipu_cmd.pos[1] = 0;
581     }
582    
583 william 62 return true;
584 william 31 }
585    
586 william 273 static __ri bool ipuPACK(tIPU_CMD_CSC csc)
587 william 31 {
588     csc.log_from_RGB32();
589    
590     for (;ipu_cmd.index < (int)csc.MBC; ipu_cmd.index++)
591     {
592 william 62 for(;ipu_cmd.pos[0] < 8; ipu_cmd.pos[0]++)
593 william 31 {
594 william 62 if (!getBits64((u8*)&decoder.mb8 + 8 * ipu_cmd.pos[0], 1)) return false;
595     }
596 william 31
597 william 62 ipu_csc(decoder.mb8, decoder.rgb32, 0);
598     ipu_dither(decoder.rgb32, decoder.rgb16, csc.DTE);
599 william 31
600 william 62 if (csc.OFM) ipu_vq(decoder.rgb16, indx4);
601 william 31
602     if (csc.OFM)
603     {
604 william 62 ipu_cmd.pos[1] += ipu_fifo.out.write(((u32*) & decoder.rgb16) + 4 * ipu_cmd.pos[1], 32 - ipu_cmd.pos[1]);
605     if (ipu_cmd.pos[1] < 32) return false;
606 william 31 }
607     else
608     {
609     ipu_cmd.pos[1] += ipu_fifo.out.write(((u32*)indx4) + 4 * ipu_cmd.pos[1], 8 - ipu_cmd.pos[1]);
610 william 62 if (ipu_cmd.pos[1] < 8) return false;
611 william 31 }
612    
613     ipu_cmd.pos[0] = 0;
614     ipu_cmd.pos[1] = 0;
615     }
616    
617     return TRUE;
618     }
619    
620     static void ipuSETTH(u32 val)
621     {
622     s_thresh[0] = (val & 0xff);
623     s_thresh[1] = ((val >> 16) & 0xff);
624 william 62 IPU_LOG("SETTH (Set threshold value)command %x.", val&0xff00ff);
625 william 31 }
626    
627 william 62 // --------------------------------------------------------------------------------------
628     // CORE Functions (referenced from MPEG library)
629     // --------------------------------------------------------------------------------------
630     __fi void ipu_csc(macroblock_8& mb8, macroblock_rgb32& rgb32, int sgn)
631 william 31 {
632 william 62 int i;
633     u8* p = (u8*)&rgb32;
634 william 31
635 william 62 yuv2rgb();
636 william 31
637 william 62 if (s_thresh[0] > 0)
638 william 31 {
639 william 62 for (i = 0; i < 16*16; i++, p += 4)
640     {
641     if ((p[0] < s_thresh[0]) && (p[1] < s_thresh[0]) && (p[2] < s_thresh[0]))
642     *(u32*)p = 0;
643     else if ((p[0] < s_thresh[1]) && (p[1] < s_thresh[1]) && (p[2] < s_thresh[1]))
644     p[3] = 0x40;
645     }
646 william 31 }
647 william 62 else if (s_thresh[1] > 0)
648     {
649     for (i = 0; i < 16*16; i++, p += 4)
650     {
651     if ((p[0] < s_thresh[1]) && (p[1] < s_thresh[1]) && (p[2] < s_thresh[1]))
652     p[3] = 0x40;
653     }
654     }
655     if (sgn)
656     {
657     for (i = 0; i < 16*16; i++, p += 4)
658     {
659     *(u32*)p ^= 0x808080;
660     }
661     }
662 william 31 }
663    
664 william 62 __fi void ipu_dither(const macroblock_rgb32& rgb32, macroblock_rgb16& rgb16, int dte)
665 william 31 {
666 william 62 int i, j;
667     for (i = 0; i < 16; ++i)
668 william 31 {
669 william 62 for (j = 0; j < 16; ++j)
670     {
671     rgb16.c[i][j].r = rgb32.c[i][j].r >> 3;
672     rgb16.c[i][j].g = rgb32.c[i][j].g >> 3;
673     rgb16.c[i][j].b = rgb32.c[i][j].b >> 3;
674     rgb16.c[i][j].a = rgb32.c[i][j].a == 0x40;
675     }
676     }
677     }
678 william 31
679 william 62 __fi void ipu_vq(macroblock_rgb16& rgb16, u8* indx4)
680     {
681     Console.Error("IPU: VQ not implemented");
682     }
683 william 31
684    
685 william 62 // --------------------------------------------------------------------------------------
686     // Buffer reader
687     // --------------------------------------------------------------------------------------
688 william 31
689 william 191 __ri u32 UBITS(uint bits)
690 william 31 {
691 william 191 uint readpos8 = g_BP.BP/8;
692 william 31
693 william 191 uint result = BigEndian(*(u32*)( (u8*)g_BP.internal_qwc + readpos8 ));
694     uint bp7 = (g_BP.BP & 7);
695     result <<= bp7;
696     result >>= (32 - bits);
697 william 31
698 william 191 return result;
699 william 31 }
700    
701 william 191 __ri s32 SBITS(uint bits)
702 william 31 {
703 william 191 // Read an unaligned 32 bit value and then shift the bits up and then back down.
704 william 31
705 william 191 uint readpos8 = g_BP.BP/8;
706 william 31
707 william 191 int result = BigEndian(*(s32*)( (s8*)g_BP.internal_qwc + readpos8 ));
708     uint bp7 = (g_BP.BP & 7);
709     result <<= bp7;
710     result >>= (32 - bits);
711 william 62
712 william 191 return result;
713 william 31 }
714    
715     // whenever reading fractions of bytes. The low bits always come from the next byte
716     // while the high bits come from the current byte
717 william 191 u8 getBits64(u8 *address, bool advance)
718 william 31 {
719 william 191 if (!g_BP.FillBuffer(64)) return 0;
720 william 31
721 william 191 const u8* readpos = &g_BP.internal_qwc[0]._u8[g_BP.BP/8];
722 william 31
723 william 62 if (uint shift = (g_BP.BP & 7))
724 william 31 {
725 william 191 u64 mask = (0xff >> shift);
726 william 62 mask = mask | (mask << 8) | (mask << 16) | (mask << 24) | (mask << 32) | (mask << 40) | (mask << 48) | (mask << 56);
727 william 31
728 william 62 *(u64*)address = ((~mask & *(u64*)(readpos + 1)) >> (8 - shift)) | (((mask) & *(u64*)readpos) << shift);
729 william 31 }
730     else
731     {
732 william 62 *(u64*)address = *(u64*)readpos;
733 william 31 }
734    
735 william 191 if (advance) g_BP.Advance(64);
736 william 31
737     return 1;
738     }
739    
740 william 62 // whenever reading fractions of bytes. The low bits always come from the next byte
741     // while the high bits come from the current byte
742 william 191 __fi u8 getBits32(u8 *address, bool advance)
743 william 31 {
744 william 191 if (!g_BP.FillBuffer(32)) return 0;
745 william 31
746 william 191 const u8* readpos = &g_BP.internal_qwc->_u8[g_BP.BP/8];
747    
748     if(uint shift = (g_BP.BP & 7))
749 william 31 {
750 william 191 u32 mask = (0xff >> shift);
751 william 62 mask = mask | (mask << 8) | (mask << 16) | (mask << 24);
752 william 31
753 william 62 *(u32*)address = ((~mask & *(u32*)(readpos + 1)) >> (8 - shift)) | (((mask) & *(u32*)readpos) << shift);
754 william 31 }
755     else
756     {
757 william 191 // Bit position-aligned -- no masking/shifting necessary
758 william 62 *(u32*)address = *(u32*)readpos;
759 william 31 }
760    
761 william 191 if (advance) g_BP.Advance(32);
762 william 31
763     return 1;
764     }
765    
766 william 191 __fi u8 getBits16(u8 *address, bool advance)
767 william 31 {
768 william 191 if (!g_BP.FillBuffer(16)) return 0;
769 william 31
770 william 191 const u8* readpos = &g_BP.internal_qwc[0]._u8[g_BP.BP/8];
771 william 31
772 william 62 if (uint shift = (g_BP.BP & 7))
773 william 31 {
774 william 191 uint mask = (0xff >> shift);
775 william 62 mask = mask | (mask << 8);
776     *(u16*)address = ((~mask & *(u16*)(readpos + 1)) >> (8 - shift)) | (((mask) & *(u16*)readpos) << shift);
777 william 191 }
778 william 31 else
779     {
780 william 62 *(u16*)address = *(u16*)readpos;
781 william 191 }
782 william 31
783 william 191 if (advance) g_BP.Advance(16);
784 william 31
785 william 62 return 1;
786 william 31 }
787    
788 william 191 u8 getBits8(u8 *address, bool advance)
789 william 31 {
790 william 191 if (!g_BP.FillBuffer(8)) return 0;
791 william 31
792 william 191 const u8* readpos = &g_BP.internal_qwc[0]._u8[g_BP.BP/8];
793 william 31
794 william 62 if (uint shift = (g_BP.BP & 7))
795 william 191 {
796     uint mask = (0xff >> shift);
797 william 62 *(u8*)address = (((~mask) & readpos[1]) >> (8 - shift)) | (((mask) & *readpos) << shift);
798 william 191 }
799 william 62 else
800 william 31 {
801 william 62 *(u8*)address = *(u8*)readpos;
802 william 191 }
803 william 31
804 william 191 if (advance) g_BP.Advance(8);
805 william 62
806     return 1;
807 william 31 }
808    
809 william 62 // --------------------------------------------------------------------------------------
810     // IPU Worker / Dispatcher
811     // --------------------------------------------------------------------------------------
812 william 273
813     // When a command is written, we set some various busy flags and clear some other junk.
814     // The actual decoding will be handled by IPUworker.
815     __fi void IPUCMD_WRITE(u32 val)
816 william 31 {
817 william 62 // don't process anything if currently busy
818 william 273 //if (ipuRegs.ctrl.BUSY) Console.WriteLn("IPU BUSY!"); // wait for thread
819 william 31
820 william 62 ipuRegs.ctrl.ECD = 0;
821 william 273 ipuRegs.ctrl.SCD = 0;
822 william 62 ipu_cmd.clear();
823     ipu_cmd.current = val;
824 william 31
825 william 273 switch (ipu_cmd.CMD)
826 william 31 {
827 william 273 // BCLR and SETTH require no data so they always execute inline:
828    
829 william 62 case SCE_IPU_BCLR:
830     ipuBCLR(val);
831     hwIntcIrq(INTC_IPU); //DMAC_TO_IPU
832 william 273 ipuRegs.ctrl.BUSY = 0;
833 william 62 return;
834 william 31
835 william 273 case SCE_IPU_SETTH:
836     ipuSETTH(val);
837     hwIntcIrq(INTC_IPU);
838     ipuRegs.ctrl.BUSY = 0;
839     return;
840 william 31
841 william 273
842    
843     case SCE_IPU_IDEC:
844 william 191 g_BP.Advance(val & 0x3F);
845 william 273 ipuIDEC(val);
846     ipuRegs.SetTopBusy();
847     break;
848 william 31
849 william 273 case SCE_IPU_BDEC:
850     g_BP.Advance(val & 0x3F);
851     ipuBDEC(val);
852     ipuRegs.SetTopBusy();
853     break;
854 william 31
855 william 273 case SCE_IPU_VDEC:
856     g_BP.Advance(val & 0x3F);
857     ipuRegs.SetDataBusy();
858 william 62 break;
859 william 31
860 william 62 case SCE_IPU_FDEC:
861 william 191 IPU_LOG("FDEC command. Skip 0x%X bits, FIFO 0x%X qwords, BP 0x%X, CHCR 0x%x",
862 william 273 val & 0x3f, g_BP.IFC, g_BP.BP, ipu1dma.chcr._u32);
863 william 191
864     g_BP.Advance(val & 0x3F);
865 william 273 ipuRegs.SetDataBusy();
866 william 62 break;
867 william 31
868 william 62 case SCE_IPU_SETIQ:
869     IPU_LOG("SETIQ command.");
870 william 191 g_BP.Advance(val & 0x3F);
871 william 62 break;
872 william 31
873 william 62 case SCE_IPU_SETVQ:
874     break;
875 william 31
876 william 62 case SCE_IPU_CSC:
877     break;
878 william 31
879 william 62 case SCE_IPU_PACK:
880     break;
881 william 31
882 william 273 jNO_DEFAULT;
883 william 62 }
884 william 31
885 william 273 ipuRegs.ctrl.BUSY = 1;
886 william 31
887 william 273 //if(!ipu1dma.chcr.STR) hwIntcIrq(INTC_IPU);
888 william 31 }
889    
890 william 273 __noinline void IPUWorker()
891 william 31 {
892 william 62 pxAssert(ipuRegs.ctrl.BUSY);
893 william 31
894 william 62 switch (ipu_cmd.CMD)
895 william 31 {
896 william 273 // These are unreachable (BUSY will always be 0 for them)
897     //case SCE_IPU_BCLR:
898     //case SCE_IPU_SETTH:
899     //break;
900    
901     case SCE_IPU_IDEC:
902     if (!mpeg2sliceIDEC()) return;
903    
904     //ipuRegs.ctrl.OFC = 0;
905     ipuRegs.topbusy = 0;
906 william 62 ipuRegs.cmd.BUSY = 0;
907 william 273
908     // CHECK!: IPU0dma remains when IDEC is done, so we need to clear it
909     // Check Mana Khemia 1 "off campus" to trigger a GUST IDEC messup.
910     // This hackfixes it :/
911 william 280 //if (ipu0dma.qwc > 0 && ipu0dma.chcr.STR) ipu0Interrupt();
912 william 273 break;
913    
914     case SCE_IPU_BDEC:
915     if (!mpeg2_slice()) return;
916    
917 william 62 ipuRegs.topbusy = 0;
918 william 273 ipuRegs.cmd.BUSY = 0;
919    
920     //if (ipuRegs.ctrl.SCD || ipuRegs.ctrl.ECD) hwIntcIrq(INTC_IPU);
921 william 62 break;
922 william 31
923 william 273 case SCE_IPU_VDEC:
924     if (!ipuVDEC(ipu_cmd.current)) return;
925    
926     ipuRegs.topbusy = 0;
927     ipuRegs.cmd.BUSY = 0;
928     break;
929    
930 william 62 case SCE_IPU_FDEC:
931 william 273 if (!ipuFDEC(ipu_cmd.current)) return;
932    
933     ipuRegs.topbusy = 0;
934 william 62 ipuRegs.cmd.BUSY = 0;
935     break;
936 william 31
937 william 62 case SCE_IPU_SETIQ:
938 william 273 if (!ipuSETIQ(ipu_cmd.current)) return;
939 william 31 break;
940    
941 william 62 case SCE_IPU_SETVQ:
942 william 273 if (!ipuSETVQ(ipu_cmd.current)) return;
943 william 62 break;
944 william 31
945 william 62 case SCE_IPU_CSC:
946 william 273 if (!ipuCSC(ipu_cmd.current)) return;
947 william 62 break;
948 william 31
949 william 62 case SCE_IPU_PACK:
950 william 273 if (!ipuPACK(ipu_cmd.current)) return;
951 william 31 break;
952    
953 william 273 jNO_DEFAULT
954 william 62 }
955 william 31
956 william 62 // success
957     ipuRegs.ctrl.BUSY = 0;
958     ipu_cmd.current = 0xffffffff;
959 william 273 hwIntcIrq(INTC_IPU);
960 william 31 }

  ViewVC Help
Powered by ViewVC 1.1.22