cdrom: change pause timing again
[pcsx_rearmed.git] / libpcsxcore / mdec.c
1 /***************************************************************************
2  *   Copyright (C) 2010 Gabriele Gorla                                     *
3  *   Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team              *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA.           *
19  ***************************************************************************/
20
21 #include "mdec.h"
22
23 /* memory speed is 1 byte per MDEC_BIAS psx clock
24  * That mean (PSXCLK / MDEC_BIAS) B/s
25  * MDEC_BIAS = 2.0 => ~16MB/s
26  * MDEC_BIAS = 3.0 => ~11MB/s
27  * and so on ...
28  * I guess I have 50 images in 50Hz ... (could be 25 images ?)
29  * 320x240x24@50Hz => 11.52 MB/s
30  * 320x240x24@60Hz => 13.824 MB/s
31  * 320x240x16@50Hz => 7.68 MB/s
32  * 320x240x16@60Hz => 9.216 MB/s
33  * so 2.0 to 4.0 should be fine.
34  */
35  
36 /*
37  * >= 10 for Galerians
38  * <= 18 for "Disney's Treasure Planet"
39  */
40 #define MDEC_BIAS 10
41
42 #define DSIZE                   8
43 #define DSIZE2                  (DSIZE * DSIZE)
44
45 #define SCALE(x, n)             ((x) >> (n))
46 #define SCALER(x, n)    (((x) + ((1 << (n)) >> 1)) >> (n))
47
48 #define AAN_CONST_BITS                  12
49 #define AAN_PRESCALE_BITS               16
50
51 #define AAN_CONST_SIZE                  24
52 #define AAN_CONST_SCALE                 (AAN_CONST_SIZE - AAN_CONST_BITS)
53
54 #define AAN_PRESCALE_SIZE               20
55 #define AAN_PRESCALE_SCALE              (AAN_PRESCALE_SIZE-AAN_PRESCALE_BITS)
56 #define AAN_EXTRA                               12
57
58 #define FIX_1_082392200         SCALER(18159528, AAN_CONST_SCALE) // B6
59 #define FIX_1_414213562         SCALER(23726566, AAN_CONST_SCALE) // A4
60 #define FIX_1_847759065         SCALER(31000253, AAN_CONST_SCALE) // A2
61 #define FIX_2_613125930         SCALER(43840978, AAN_CONST_SCALE) // B2
62
63 #define MULS(var, const)        (SCALE((var) * (const), AAN_CONST_BITS))
64
65 #define RLE_RUN(a)      ((a) >> 10)
66 #define RLE_VAL(a)      (((int)(a) << (sizeof(int) * 8 - 10)) >> (sizeof(int) * 8 - 10))
67
68 #if 0
69 static void printmatrixu8(u8 *m) {
70         int i;
71         for(i = 0; i < DSIZE2; i++) {
72                 printf("%3d ",m[i]);
73                 if((i+1) % 8 == 0) printf("\n");
74         }
75 }
76 #endif
77
78 static inline void fillcol(int *blk, int val) {
79         blk[0 * DSIZE] = blk[1 * DSIZE] = blk[2 * DSIZE] = blk[3 * DSIZE]
80                 = blk[4 * DSIZE] = blk[5 * DSIZE] = blk[6 * DSIZE] = blk[7 * DSIZE] = val;
81 }
82
83 static inline void fillrow(int *blk, int val) {
84         blk[0] = blk[1] = blk[2] = blk[3]
85                 = blk[4] = blk[5] = blk[6] = blk[7] = val;
86 }
87
88 static void idct(int *block,int used_col) {
89         int tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
90         int z5, z10, z11, z12, z13;
91         int *ptr;
92         int i;
93
94         // the block has only the DC coefficient
95         if (used_col == -1) { 
96                 int v = block[0];
97                 for (i = 0; i < DSIZE2; i++) block[i] = v;
98                 return;
99         }
100
101         // last_col keeps track of the highest column with non zero coefficients
102         ptr = block;
103         for (i = 0; i < DSIZE; i++, ptr++) {
104                 if ((used_col & (1 << i)) == 0) {
105                         // the column is empty or has only the DC coefficient
106                         if (ptr[DSIZE * 0]) {
107                                 fillcol(ptr, ptr[0]);
108                                 used_col |= (1 << i);
109                         }
110                         continue;
111                 }
112
113                 // further optimization could be made by keeping track of 
114                 // last_row in rl2blk
115                 z10 = ptr[DSIZE * 0] + ptr[DSIZE * 4]; // s04
116                 z11 = ptr[DSIZE * 0] - ptr[DSIZE * 4]; // d04
117                 z13 = ptr[DSIZE * 2] + ptr[DSIZE * 6]; // s26
118                 z12 = MULS(ptr[DSIZE * 2] - ptr[DSIZE * 6], FIX_1_414213562) - z13; 
119                 //^^^^  d26=d26*2*A4-s26
120
121                 tmp0 = z10 + z13; // os07 = s04 + s26
122                 tmp3 = z10 - z13; // os34 = s04 - s26
123                 tmp1 = z11 + z12; // os16 = d04 + d26
124                 tmp2 = z11 - z12; // os25 = d04 - d26
125
126                 z13 = ptr[DSIZE * 3] + ptr[DSIZE * 5]; //s53
127                 z10 = ptr[DSIZE * 3] - ptr[DSIZE * 5]; //-d53 
128                 z11 = ptr[DSIZE * 1] + ptr[DSIZE * 7]; //s17
129                 z12 = ptr[DSIZE * 1] - ptr[DSIZE * 7]; //d17
130
131                 tmp7 = z11 + z13; // od07 = s17 + s53
132
133                 z5 = (z12 - z10) * (FIX_1_847759065); 
134                 tmp6 = SCALE(z10*(FIX_2_613125930) + z5, AAN_CONST_BITS) - tmp7; 
135                 tmp5 = MULS(z11 - z13, FIX_1_414213562) - tmp6;
136                 tmp4 = SCALE(z12*(FIX_1_082392200) - z5, AAN_CONST_BITS) + tmp5; 
137
138                 // path #1
139                 //z5 = (z12 - z10)* FIX_1_847759065; 
140                 // tmp0 = (d17 + d53) * 2*A2
141
142                 //tmp6 = DESCALE(z10*FIX_2_613125930 + z5, CONST_BITS) - tmp7; 
143                 // od16 = (d53*-2*B2 + tmp0) - od07
144
145                 //tmp4 = DESCALE(z12*FIX_1_082392200 - z5, CONST_BITS) + tmp5; 
146                 // od34 = (d17*2*B6 - tmp0) + od25
147
148                 // path #2
149
150                 // od34 = d17*2*(B6-A2) - d53*2*A2
151                 // od16 = d53*2*(A2-B2) + d17*2*A2
152
153                 // end
154
155                 //    tmp5 = MULS(z11 - z13, FIX_1_414213562) - tmp6;
156                 // od25 = (s17 - s53)*2*A4 - od16
157
158                 ptr[DSIZE * 0] = (tmp0 + tmp7); // os07 + od07
159                 ptr[DSIZE * 7] = (tmp0 - tmp7); // os07 - od07
160                 ptr[DSIZE * 1] = (tmp1 + tmp6); // os16 + od16
161                 ptr[DSIZE * 6] = (tmp1 - tmp6); // os16 - od16
162                 ptr[DSIZE * 2] = (tmp2 + tmp5); // os25 + od25
163                 ptr[DSIZE * 5] = (tmp2 - tmp5); // os25 - od25
164                 ptr[DSIZE * 4] = (tmp3 + tmp4); // os34 + od34
165                 ptr[DSIZE * 3] = (tmp3 - tmp4); // os34 - od34
166         }
167
168         ptr = block;
169         if (used_col == 1) {
170                 for (i = 0; i < DSIZE; i++)
171                         fillrow(block + DSIZE * i, block[DSIZE * i]);    
172         } else {
173                 for (i = 0; i < DSIZE; i++, ptr += DSIZE) {
174                         z10 = ptr[0] + ptr[4];
175                         z11 = ptr[0] - ptr[4];
176                         z13 = ptr[2] + ptr[6];
177                         z12 = MULS(ptr[2] - ptr[6], FIX_1_414213562) - z13;
178
179                         tmp0 = z10 + z13;
180                         tmp3 = z10 - z13;
181                         tmp1 = z11 + z12;
182                         tmp2 = z11 - z12;
183                         
184                         z13 = ptr[3] + ptr[5];
185                         z10 = ptr[3] - ptr[5];
186                         z11 = ptr[1] + ptr[7];
187                         z12 = ptr[1] - ptr[7];
188
189                         tmp7 = z11 + z13;
190                         z5 = (z12 - z10) * FIX_1_847759065; 
191                         tmp6 = SCALE(z10 * FIX_2_613125930 + z5, AAN_CONST_BITS) - tmp7;
192                         tmp5 = MULS(z11 - z13, FIX_1_414213562) - tmp6;
193                         tmp4 = SCALE(z12 * FIX_1_082392200 - z5, AAN_CONST_BITS) + tmp5;
194
195                         ptr[0] = tmp0 + tmp7;
196
197                         ptr[7] = tmp0 - tmp7;
198                         ptr[1] = tmp1 + tmp6;
199                         ptr[6] = tmp1 - tmp6;
200                         ptr[2] = tmp2 + tmp5;
201                         ptr[5] = tmp2 - tmp5;
202                         ptr[4] = tmp3 + tmp4;
203                         ptr[3] = tmp3 - tmp4;
204                 }
205         }
206 }
207
208 // mdec0: command register
209 #define MDEC0_STP                       0x02000000
210 #define MDEC0_RGB24                     0x08000000
211 #define MDEC0_SIZE_MASK         0x0000FFFF
212
213 // mdec1: status register
214 #define MDEC1_BUSY                      0x20000000
215 #define MDEC1_DREQ                      0x18000000
216 #define MDEC1_FIFO                      0xc0000000
217 #define MDEC1_RGB24                     0x02000000
218 #define MDEC1_STP                       0x00800000
219 #define MDEC1_RESET                     0x80000000
220
221 struct _pending_dma1 {
222         u32 adr;
223         u32 bcr;
224         u32 chcr;
225 };
226
227 static struct {
228         u32 reg0;
229         u32 reg1;
230         const u16 * rl;
231         const u16 * rl_end;
232         u8 * block_buffer_pos;
233         u8 block_buffer[16*16*3];
234         struct _pending_dma1 pending_dma1;
235 } mdec;
236
237 static int iq_y[DSIZE2], iq_uv[DSIZE2];
238
239 static int zscan[DSIZE2] = {
240         0 , 1 , 8 , 16, 9 , 2 , 3 , 10,
241         17, 24, 32, 25, 18, 11, 4 , 5 ,
242         12, 19, 26, 33, 40, 48, 41, 34,
243         27, 20, 13, 6 , 7 , 14, 21, 28,
244         35, 42, 49, 56, 57, 50, 43, 36,
245         29, 22, 15, 23, 30, 37, 44, 51,
246         58, 59, 52, 45, 38, 31, 39, 46,
247         53, 60, 61, 54, 47, 55, 62, 63
248 };
249
250 static int aanscales[DSIZE2] = {
251         1048576, 1454417, 1370031, 1232995, 1048576,  823861, 567485, 289301,
252         1454417, 2017334, 1900287, 1710213, 1454417, 1142728, 787125, 401273,
253         1370031, 1900287, 1790031, 1610986, 1370031, 1076426, 741455, 377991,
254         1232995, 1710213, 1610986, 1449849, 1232995,  968758, 667292, 340183,
255         1048576, 1454417, 1370031, 1232995, 1048576,  823861, 567485, 289301,
256         823861,  1142728, 1076426, 968758,  823861,  647303, 445870, 227303,
257         567485,  787125,  741455,  667292,  567485,  445870, 307121, 156569,
258         289301,  401273,  377991,  340183,  289301,  227303, 156569,  79818
259 };
260
261 static void iqtab_init(int *iqtab, const unsigned char *iq_y) {
262         int i;
263
264         for (i = 0; i < DSIZE2; i++) {
265                 iqtab[i] = (iq_y[i] * SCALER(aanscales[zscan[i]], AAN_PRESCALE_SCALE));
266         }
267 }
268
269 #define MDEC_END_OF_DATA        0xfe00
270
271 static const unsigned short *rl2blk(int *blk, const unsigned short *mdec_rl) {
272         int i, k, q_scale, rl, used_col;
273         int *iqtab;
274
275         memset(blk, 0, 6 * DSIZE2 * sizeof(int));
276         iqtab = iq_uv;
277         for (i = 0; i < 6; i++) {
278                 // decode blocks (Cr,Cb,Y1,Y2,Y3,Y4)
279                 if (i == 2) iqtab = iq_y;
280
281                 rl = SWAP16(*mdec_rl); mdec_rl++;
282                 q_scale = RLE_RUN(rl);
283                 blk[0] = SCALER(iqtab[0] * RLE_VAL(rl), AAN_EXTRA - 3);
284                 for (k = 0, used_col = 0;;) {
285                         rl = SWAP16(*mdec_rl); mdec_rl++;
286                         if (rl == MDEC_END_OF_DATA) break;
287                         k += RLE_RUN(rl) + 1;   // skip zero-coefficients
288
289                         if (k > 63) {
290                                 // printf("run lenght exceeded 64 enties\n");
291                                 break;
292                         }
293
294                         // zigzag transformation
295                         blk[zscan[k]] = SCALER(RLE_VAL(rl) * iqtab[k] * q_scale, AAN_EXTRA);
296                         // keep track of used columns to speed up the idtc
297                         used_col |= (zscan[k] > 7) ? 1 << (zscan[k] & 7) : 0;
298                 }
299
300                 if (k == 0) used_col = -1;
301                 // used_col is -1 for blocks with only the DC coefficient
302                 // any other value is a bitmask of the columns that have 
303                 // at least one non zero cofficient in the rows 1-7
304                 // single coefficients in row 0 are treted specially 
305                 // in the idtc function
306                 idct(blk, used_col);
307                 blk += DSIZE2;
308         }
309         return mdec_rl;
310 }
311
312 // full scale (JPEG)
313 // Y/Cb/Cr[0...255] -> R/G/B[0...255]
314 // R = 1.000 * (Y) + 1.400 * (Cr - 128)
315 // G = 1.000 * (Y) - 0.343 * (Cb - 128) - 0.711 (Cr - 128)
316 // B = 1.000 * (Y) + 1.765 * (Cb - 128)
317 #define MULR(a)                 ((1434 * (a))) 
318 #define MULB(a)                 ((1807 * (a))) 
319 #define MULG2(a, b)             ((-351 * (a) - 728 * (b)))
320 #define MULY(a)                 ((a) << 10)
321
322 #define MAKERGB15(r, g, b, a)   (SWAP16(a | ((b) << 10) | ((g) << 5) | (r)))
323 #define SCALE8(c)                               SCALER(c, 20) 
324 #define SCALE5(c)                               SCALER(c, 23)
325
326 #define CLAMP5(c)       ( ((c) < -16) ? 0 : (((c) > (31 - 16)) ? 31 : ((c) + 16)) )
327 #define CLAMP8(c)       ( ((c) < -128) ? 0 : (((c) > (255 - 128)) ? 255 : ((c) + 128)) )
328
329 #define CLAMP_SCALE8(a)   (CLAMP8(SCALE8(a)))
330 #define CLAMP_SCALE5(a)   (CLAMP5(SCALE5(a)))
331
332 static inline void putlinebw15(u16 *image, int *Yblk) {
333         int i;
334         int A = (mdec.reg0 & MDEC0_STP) ? 0x8000 : 0;
335
336         for (i = 0; i < 8; i++, Yblk++) {
337                 int Y = *Yblk;
338                 // missing rounding
339                 image[i] = SWAP16((CLAMP5(Y >> 3) * 0x421) | A);
340         }
341 }
342
343 static inline void putquadrgb15(u16 *image, int *Yblk, int Cr, int Cb) {
344         int Y, R, G, B;
345         int A = (mdec.reg0 & MDEC0_STP) ? 0x8000 : 0;
346         R = MULR(Cr);
347         G = MULG2(Cb, Cr);
348         B = MULB(Cb);
349
350         // added transparency
351         Y = MULY(Yblk[0]);
352         image[0] = MAKERGB15(CLAMP_SCALE5(Y + R), CLAMP_SCALE5(Y + G), CLAMP_SCALE5(Y + B), A);
353         Y = MULY(Yblk[1]);
354         image[1] = MAKERGB15(CLAMP_SCALE5(Y + R), CLAMP_SCALE5(Y + G), CLAMP_SCALE5(Y + B), A);
355         Y = MULY(Yblk[8]);
356         image[16] = MAKERGB15(CLAMP_SCALE5(Y + R), CLAMP_SCALE5(Y + G), CLAMP_SCALE5(Y + B), A);
357         Y = MULY(Yblk[9]);
358         image[17] = MAKERGB15(CLAMP_SCALE5(Y + R), CLAMP_SCALE5(Y + G), CLAMP_SCALE5(Y + B), A);
359 }
360
361 static inline void yuv2rgb15(int *blk, unsigned short *image) {
362         int x, y;
363         int *Yblk = blk + DSIZE2 * 2;
364         int *Crblk = blk;
365         int *Cbblk = blk + DSIZE2;
366
367         if (!Config.Mdec) {
368                 for (y = 0; y < 16; y += 2, Crblk += 4, Cbblk += 4, Yblk += 8, image += 24) {
369                         if (y == 8) Yblk += DSIZE2;
370                         for (x = 0; x < 4; x++, image += 2, Crblk++, Cbblk++, Yblk += 2) {
371                                 putquadrgb15(image, Yblk, *Crblk, *Cbblk);
372                                 putquadrgb15(image + 8, Yblk + DSIZE2, *(Crblk + 4), *(Cbblk + 4));
373                         }
374                 } 
375         } else {
376                 for (y = 0; y < 16; y++, Yblk += 8, image += 16) {
377                         if (y == 8) Yblk += DSIZE2;
378                         putlinebw15(image, Yblk);
379                         putlinebw15(image + 8, Yblk + DSIZE2);
380                 }
381         }
382 }
383
384 static inline void putlinebw24(u8 * image, int *Yblk) {
385         int i;
386         unsigned char Y;
387         for (i = 0; i < 8 * 3; i += 3, Yblk++) {
388                 Y = CLAMP8(*Yblk);
389                 image[i + 0] = Y;
390                 image[i + 1] = Y;
391                 image[i + 2] = Y;
392         }
393 }
394
395 static inline void putquadrgb24(u8 * image, int *Yblk, int Cr, int Cb) {
396         int Y, R, G, B;
397
398         R = MULR(Cr);
399         G = MULG2(Cb,Cr);
400         B = MULB(Cb);
401
402         Y = MULY(Yblk[0]);
403         image[0 * 3 + 0] = CLAMP_SCALE8(Y + R);
404         image[0 * 3 + 1] = CLAMP_SCALE8(Y + G);
405         image[0 * 3 + 2] = CLAMP_SCALE8(Y + B);
406         Y = MULY(Yblk[1]);
407         image[1 * 3 + 0] = CLAMP_SCALE8(Y + R);
408         image[1 * 3 + 1] = CLAMP_SCALE8(Y + G);
409         image[1 * 3 + 2] = CLAMP_SCALE8(Y + B);
410         Y = MULY(Yblk[8]);
411         image[16 * 3 + 0] = CLAMP_SCALE8(Y + R);
412         image[16 * 3 + 1] = CLAMP_SCALE8(Y + G);
413         image[16 * 3 + 2] = CLAMP_SCALE8(Y + B);
414         Y = MULY(Yblk[9]);
415         image[17 * 3 + 0] = CLAMP_SCALE8(Y + R);
416         image[17 * 3 + 1] = CLAMP_SCALE8(Y + G);
417         image[17 * 3 + 2] = CLAMP_SCALE8(Y + B);
418 }
419
420 static void yuv2rgb24(int *blk, u8 *image) {
421         int x, y;
422         int *Yblk = blk + DSIZE2 * 2;
423         int *Crblk = blk;
424         int *Cbblk = blk + DSIZE2;
425
426         if (!Config.Mdec) {
427                 for (y = 0; y < 16; y += 2, Crblk += 4, Cbblk += 4, Yblk += 8, image += 8 * 3 * 3) {
428                         if (y == 8) Yblk += DSIZE2;
429                         for (x = 0; x < 4; x++, image += 6, Crblk++, Cbblk++, Yblk += 2) {
430                                 putquadrgb24(image, Yblk, *Crblk, *Cbblk);
431                                 putquadrgb24(image + 8 * 3, Yblk + DSIZE2, *(Crblk + 4), *(Cbblk + 4));
432                         }
433                 }
434         } else {
435                 for (y = 0; y < 16; y++, Yblk += 8, image += 16 * 3) {
436                         if (y == 8) Yblk += DSIZE2;
437                         putlinebw24(image, Yblk);
438                         putlinebw24(image + 8 * 3, Yblk + DSIZE2);
439                 }
440         }
441 }
442
443 void mdecInit(void) {
444         memset(&mdec, 0, sizeof(mdec));
445         memset(iq_y, 0, sizeof(iq_y));
446         memset(iq_uv, 0, sizeof(iq_uv));
447         mdec.rl = (u16 *)&psxM[0x100000];
448 }
449
450 // command register
451 void mdecWrite0(u32 data) {
452         mdec.reg0 = data;
453 }
454
455 u32 mdecRead0(void) {
456         return mdec.reg0;
457 }
458
459 // status register
460 void mdecWrite1(u32 data) {
461         if (data & MDEC1_RESET) { // mdec reset
462                 mdec.reg0 = 0;
463                 mdec.reg1 = 0;
464                 mdec.pending_dma1.adr = 0;
465                 mdec.block_buffer_pos = 0;
466         }
467 }
468
469 u32 mdecRead1(void) {
470         u32 v = mdec.reg1;
471         return v;
472 }
473
474 void psxDma0(u32 adr, u32 bcr, u32 chcr) {
475         u32 cmd = mdec.reg0, words_max = 0;
476         const void *mem;
477         int size;
478
479         if (chcr != 0x01000201) {
480                 log_unhandled("mdec0: invalid dma %08x\n", chcr);
481                 return;
482         }
483
484         /* mdec is STP till dma0 is released */
485         mdec.reg1 |= MDEC1_STP;
486
487         size = (bcr >> 16) * (bcr & 0xffff);
488
489         adr &= ~3;
490         mem = getDmaRam(adr, &words_max);
491         if (mem == INVALID_PTR || size > words_max) {
492                 log_unhandled("bad dma0 madr %x\n", adr);
493                 HW_DMA0_CHCR &= SWAP32(~0x01000000);
494                 return;
495         }
496
497         switch (cmd >> 28) {
498                 case 0x3: // decode 15/24bpp
499                         mdec.rl = mem;
500                         /* now the mdec is busy till all data are decoded */
501                         mdec.reg1 |= MDEC1_BUSY;
502                         /* detect the end of decoding */
503                         mdec.rl_end = mdec.rl + (size * 2);
504
505                         /* sanity check */
506                         if(mdec.rl_end <= mdec.rl)
507                                 break;
508
509                         /* process the pending dma1 */
510                         if(mdec.pending_dma1.adr){
511                                 psxDma1(mdec.pending_dma1.adr, mdec.pending_dma1.bcr, mdec.pending_dma1.chcr);
512                         }
513                         mdec.pending_dma1.adr = 0;
514                         return;
515                         
516
517                 case 0x4: // quantization table upload
518                         {
519                                 const u8 *p = mem;
520                                 // printf("uploading new quantization table\n");
521                                 // printmatrixu8(p);
522                                 // printmatrixu8(p + 64);
523                                 iqtab_init(iq_y, p);
524                                 iqtab_init(iq_uv, p + 64);
525                         }
526                         break;
527
528                 case 0x6: // cosine table
529                         // printf("mdec cosine table\n");
530                         break;
531
532                 default:
533                         log_unhandled("mdec: unknown command %08x\n", cmd);
534                         break;
535         }
536
537         set_event(PSXINT_MDECINDMA, size);
538 }
539
540 void mdec0Interrupt()
541 {
542         if (HW_DMA0_CHCR & SWAP32(0x01000000))
543         {
544                 HW_DMA0_CHCR &= SWAP32(~0x01000000);
545                 DMA_INTERRUPT(0);
546         }
547 }
548
549 #define SIZE_OF_24B_BLOCK (16*16*3)
550 #define SIZE_OF_16B_BLOCK (16*16*2)
551
552 void psxDma1(u32 adr, u32 bcr, u32 chcr) {
553         u32 words, words_max = 0;
554         int blk[DSIZE2 * 6];
555         u8 * image;
556         int size;
557
558         if (chcr != 0x01000200) {
559                 log_unhandled("mdec1: invalid dma %08x\n", chcr);
560                 return;
561         }
562
563         words = (bcr >> 16) * (bcr & 0xffff);
564         /* size in byte */
565         size = words * 4;
566
567         if (!(mdec.reg1 & MDEC1_BUSY)) {
568                 /* add to pending */
569                 mdec.pending_dma1.adr = adr;
570                 mdec.pending_dma1.bcr = bcr;
571                 mdec.pending_dma1.chcr = chcr;
572                 /* do not free the dma */
573                 return;
574         }
575
576         adr &= ~3;
577         image = getDmaRam(adr, &words_max);
578         if (image == INVALID_PTR || words > words_max) {
579                 log_unhandled("bad dma1 madr %x\n", adr);
580                 HW_DMA1_CHCR &= SWAP32(~0x01000000);
581                 return;
582         }
583
584         if (mdec.reg0 & MDEC0_RGB24) {
585                 /* 16 bits decoding
586                  * block are 16 px * 16 px, each px are 2 byte
587                  */
588
589                 /* there is some partial block pending ? */
590                 if(mdec.block_buffer_pos != 0) {
591                         int n = mdec.block_buffer - mdec.block_buffer_pos + SIZE_OF_16B_BLOCK;
592                         /* TODO: check if partial block do not  larger than size */
593                         memcpy(image, mdec.block_buffer_pos, n);
594                         image += n;
595                         size -= n;
596                         mdec.block_buffer_pos = 0;
597                 }
598
599                 while(size >= SIZE_OF_16B_BLOCK) {
600                         mdec.rl = rl2blk(blk, mdec.rl);
601                         yuv2rgb15(blk, (u16 *)image);
602                         image += SIZE_OF_16B_BLOCK;
603                         size -= SIZE_OF_16B_BLOCK;
604                 }
605
606                 if(size != 0) {
607                         mdec.rl = rl2blk(blk, mdec.rl);
608                         yuv2rgb15(blk, (u16 *)mdec.block_buffer);
609                         memcpy(image, mdec.block_buffer, size);
610                         mdec.block_buffer_pos = mdec.block_buffer + size;
611                 }
612
613         } else {
614                 /* 24 bits decoding
615                  * block are 16 px * 16 px, each px are 3 byte
616                  */
617
618                 /* there is some partial block pending ? */
619                 if(mdec.block_buffer_pos != 0) {
620                         int n = mdec.block_buffer - mdec.block_buffer_pos + SIZE_OF_24B_BLOCK;
621                         /* TODO: check if partial block do not  larger than size */
622                         memcpy(image, mdec.block_buffer_pos, n);
623                         image += n;
624                         size -= n;
625                         mdec.block_buffer_pos = 0;
626                 }
627
628                 while(size >= SIZE_OF_24B_BLOCK) {
629                         mdec.rl = rl2blk(blk, mdec.rl);
630                         yuv2rgb24(blk, image);
631                         image += SIZE_OF_24B_BLOCK;
632                         size -= SIZE_OF_24B_BLOCK;
633                 }
634
635                 if(size != 0) {
636                         mdec.rl = rl2blk(blk, mdec.rl);
637                         yuv2rgb24(blk, mdec.block_buffer);
638                         memcpy(image, mdec.block_buffer, size);
639                         mdec.block_buffer_pos = mdec.block_buffer + size;
640                 }
641         }
642         if (size < 0)
643                 log_unhandled("mdec: bork\n");
644         
645         /* define the power of mdec */
646         set_event(PSXINT_MDECOUTDMA, words * MDEC_BIAS);
647         /* some CPU stalling */
648         psxRegs.cycle += words;
649 }
650
651 void mdec1Interrupt() {
652         /* Author : gschwind
653          *
654          * in that case we have done all decoding stuff
655          * Note that : each block end with 0xfe00 flags
656          * the list of blocks end with the same 0xfe00 flags
657          * data loock like :
658          *
659          *  data block ...
660          *  0xfe00
661          *  data block ...
662          *  0xfe00
663          *  a lost of block ..
664          *
665          *  0xfe00
666          *  the last block
667          *  0xfe00
668          *  0xfe00
669          *
670          * OR
671          *
672          * if the 0xfe00 is not present the data size is important.
673          *
674          */
675
676         /* MDEC_END_OF_DATA avoids read outside memory */
677         //printf("mdec left %zd, v=%04x\n", mdec.rl_end - mdec.rl, *(mdec.rl));
678         if (mdec.rl >= mdec.rl_end || SWAP16(*(mdec.rl)) == MDEC_END_OF_DATA) {
679                 mdec.reg1 &= ~(MDEC1_STP|MDEC1_BUSY);
680                 if (HW_DMA0_CHCR & SWAP32(0x01000000))
681                 {
682                         HW_DMA0_CHCR &= SWAP32(~0x01000000);
683                         DMA_INTERRUPT(0);
684                 }
685         }
686
687         if (HW_DMA1_CHCR & SWAP32(0x01000000))
688         {
689                 HW_DMA1_CHCR &= SWAP32(~0x01000000);
690                 DMA_INTERRUPT(1);
691         }
692 }
693
694 int mdecFreeze(void *f, int Mode) {
695         u8 *base = (u8 *)psxM;
696         u32 v;
697
698         gzfreeze(&mdec.reg0, sizeof(mdec.reg0));
699         gzfreeze(&mdec.reg1, sizeof(mdec.reg1));
700
701         v = (u8 *)mdec.rl - base;
702         gzfreeze(&v, sizeof(v));
703         mdec.rl = (u16 *)(base + (v & 0x1ffffe));
704         v = (u8 *)mdec.rl_end - base;
705         gzfreeze(&v, sizeof(v));
706         mdec.rl_end = (u16 *)(base + (v & 0x1ffffe));
707
708         v = 0;
709         if (mdec.block_buffer_pos)
710                 v = mdec.block_buffer_pos - mdec.block_buffer;
711         gzfreeze(&v, sizeof(v));
712         mdec.block_buffer_pos = 0;
713         if (v && v < sizeof(mdec.block_buffer))
714                 mdec.block_buffer_pos = mdec.block_buffer;
715
716         gzfreeze(&mdec.block_buffer, sizeof(mdec.block_buffer));
717         gzfreeze(&mdec.pending_dma1, sizeof(mdec.pending_dma1));
718         gzfreeze(iq_y, sizeof(iq_y));
719         gzfreeze(iq_uv, sizeof(iq_uv));
720
721         return 0;
722 }