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