cdrom: change pause timing again
[pcsx_rearmed.git] / libpcsxcore / mdec.c
CommitLineData
ef79bbde
P
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
528ad661 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 */
1ffdacd5 35
4f329f16 36/*
37 * >= 10 for Galerians
38 * <= 18 for "Disney's Treasure Planet"
39 */
1ffdacd5 40#define MDEC_BIAS 10
528ad661 41
ef79bbde
P
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
69static 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
78static 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
83static 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
528ad661 88static void idct(int *block,int used_col) {
ef79bbde
P
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
528ad661 211#define MDEC0_SIZE_MASK 0x0000FFFF
ef79bbde
P
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
528ad661 221struct _pending_dma1 {
222 u32 adr;
223 u32 bcr;
224 u32 chcr;
225};
226
c62b43c9 227static struct {
528ad661 228 u32 reg0;
229 u32 reg1;
b54a1ac7 230 const u16 * rl;
231 const u16 * rl_end;
528ad661 232 u8 * block_buffer_pos;
233 u8 block_buffer[16*16*3];
234 struct _pending_dma1 pending_dma1;
ef79bbde
P
235} mdec;
236
237static int iq_y[DSIZE2], iq_uv[DSIZE2];
238
239static 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
250static 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
b54a1ac7 261static void iqtab_init(int *iqtab, const unsigned char *iq_y) {
ef79bbde
P
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
b54a1ac7 271static const unsigned short *rl2blk(int *blk, const unsigned short *mdec_rl) {
ef79bbde
P
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
528ad661 332static inline void putlinebw15(u16 *image, int *Yblk) {
ef79bbde
P
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
528ad661 343static inline void putquadrgb15(u16 *image, int *Yblk, int Cr, int Cb) {
ef79bbde
P
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
528ad661 361static inline void yuv2rgb15(int *blk, unsigned short *image) {
ef79bbde
P
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
528ad661 384static inline void putlinebw24(u8 * image, int *Yblk) {
ef79bbde
P
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
528ad661 395static inline void putquadrgb24(u8 * image, int *Yblk, int Cr, int Cb) {
ef79bbde
P
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
528ad661 420static void yuv2rgb24(int *blk, u8 *image) {
ef79bbde
P
421 int x, y;
422 int *Yblk = blk + DSIZE2 * 2;
423 int *Crblk = blk;
424 int *Cbblk = blk + DSIZE2;
425
426 if (!Config.Mdec) {
528ad661 427 for (y = 0; y < 16; y += 2, Crblk += 4, Cbblk += 4, Yblk += 8, image += 8 * 3 * 3) {
ef79bbde
P
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
443void mdecInit(void) {
c62b43c9 444 memset(&mdec, 0, sizeof(mdec));
445 memset(iq_y, 0, sizeof(iq_y));
446 memset(iq_uv, 0, sizeof(iq_uv));
ef79bbde 447 mdec.rl = (u16 *)&psxM[0x100000];
ef79bbde
P
448}
449
450// command register
451void mdecWrite0(u32 data) {
ef79bbde
P
452 mdec.reg0 = data;
453}
454
455u32 mdecRead0(void) {
ef79bbde
P
456 return mdec.reg0;
457}
458
459// status register
460void mdecWrite1(u32 data) {
ef79bbde
P
461 if (data & MDEC1_RESET) { // mdec reset
462 mdec.reg0 = 0;
463 mdec.reg1 = 0;
528ad661 464 mdec.pending_dma1.adr = 0;
465 mdec.block_buffer_pos = 0;
ef79bbde
P
466 }
467}
468
469u32 mdecRead1(void) {
470 u32 v = mdec.reg1;
ef79bbde
P
471 return v;
472}
473
474void psxDma0(u32 adr, u32 bcr, u32 chcr) {
b54a1ac7 475 u32 cmd = mdec.reg0, words_max = 0;
476 const void *mem;
ef79bbde 477 int size;
ef79bbde
P
478
479 if (chcr != 0x01000201) {
8c84ba5f 480 log_unhandled("mdec0: invalid dma %08x\n", chcr);
ef79bbde
P
481 return;
482 }
483
528ad661 484 /* mdec is STP till dma0 is released */
485 mdec.reg1 |= MDEC1_STP;
486
ef79bbde
P
487 size = (bcr >> 16) * (bcr & 0xffff);
488
b54a1ac7 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
ef79bbde 497 switch (cmd >> 28) {
4f329f16 498 case 0x3: // decode 15/24bpp
b54a1ac7 499 mdec.rl = mem;
528ad661 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 */
4f329f16 506 if(mdec.rl_end <= mdec.rl)
507 break;
528ad661 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
ef79bbde
P
516
517 case 0x4: // quantization table upload
518 {
b54a1ac7 519 const u8 *p = mem;
ef79bbde
P
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 }
4f329f16 526 break;
ef79bbde
P
527
528 case 0x6: // cosine table
529 // printf("mdec cosine table\n");
4f329f16 530 break;
ef79bbde
P
531
532 default:
6c9db47c 533 log_unhandled("mdec: unknown command %08x\n", cmd);
ef79bbde
P
534 break;
535 }
536
9a0a61d2 537 set_event(PSXINT_MDECINDMA, size);
ef79bbde
P
538}
539
528ad661 540void mdec0Interrupt()
541{
ad418c19 542 if (HW_DMA0_CHCR & SWAP32(0x01000000))
543 {
544 HW_DMA0_CHCR &= SWAP32(~0x01000000);
545 DMA_INTERRUPT(0);
546 }
528ad661 547}
548
549#define SIZE_OF_24B_BLOCK (16*16*3)
550#define SIZE_OF_16B_BLOCK (16*16*2)
551
ef79bbde 552void psxDma1(u32 adr, u32 bcr, u32 chcr) {
b54a1ac7 553 u32 words, words_max = 0;
ef79bbde 554 int blk[DSIZE2 * 6];
528ad661 555 u8 * image;
ef79bbde 556 int size;
ef79bbde 557
8c84ba5f 558 if (chcr != 0x01000200) {
559 log_unhandled("mdec1: invalid dma %08x\n", chcr);
560 return;
561 }
ef79bbde 562
fc4803bd 563 words = (bcr >> 16) * (bcr & 0xffff);
528ad661 564 /* size in byte */
fc4803bd 565 size = words * 4;
528ad661 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 */
b54a1ac7 573 return;
574 }
ef79bbde 575
b54a1ac7 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 }
528ad661 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 }
ef79bbde 598
528ad661 599 while(size >= SIZE_OF_16B_BLOCK) {
ef79bbde 600 mdec.rl = rl2blk(blk, mdec.rl);
528ad661 601 yuv2rgb15(blk, (u16 *)image);
602 image += SIZE_OF_16B_BLOCK;
603 size -= SIZE_OF_16B_BLOCK;
ef79bbde 604 }
528ad661 605
606 if(size != 0) {
ef79bbde 607 mdec.rl = rl2blk(blk, mdec.rl);
528ad661 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;
ef79bbde 633 }
ef79bbde 634
528ad661 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 }
b54a1ac7 642 if (size < 0)
643 log_unhandled("mdec: bork\n");
528ad661 644
b54a1ac7 645 /* define the power of mdec */
646 set_event(PSXINT_MDECOUTDMA, words * MDEC_BIAS);
647 /* some CPU stalling */
648 psxRegs.cycle += words;
ef79bbde
P
649}
650
651void mdec1Interrupt() {
528ad661 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
ad418c19 676 /* MDEC_END_OF_DATA avoids read outside memory */
b54a1ac7 677 //printf("mdec left %zd, v=%04x\n", mdec.rl_end - mdec.rl, *(mdec.rl));
ad418c19 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 }
ef79bbde 685 }
528ad661 686
ad418c19 687 if (HW_DMA1_CHCR & SWAP32(0x01000000))
688 {
689 HW_DMA1_CHCR &= SWAP32(~0x01000000);
690 DMA_INTERRUPT(1);
691 }
ef79bbde
P
692}
693
496d88d4 694int mdecFreeze(void *f, int Mode) {
b34d6a80 695 u8 *base = (u8 *)psxM;
8e1040b6 696 u32 v;
697
698 gzfreeze(&mdec.reg0, sizeof(mdec.reg0));
699 gzfreeze(&mdec.reg1, sizeof(mdec.reg1));
700
8e1040b6 701 v = (u8 *)mdec.rl - base;
702 gzfreeze(&v, sizeof(v));
b34d6a80 703 mdec.rl = (u16 *)(base + (v & 0x1ffffe));
8e1040b6 704 v = (u8 *)mdec.rl_end - base;
705 gzfreeze(&v, sizeof(v));
b34d6a80 706 mdec.rl_end = (u16 *)(base + (v & 0x1ffffe));
8e1040b6 707
708 v = 0;
709 if (mdec.block_buffer_pos)
b34d6a80 710 v = mdec.block_buffer_pos - mdec.block_buffer;
8e1040b6 711 gzfreeze(&v, sizeof(v));
712 mdec.block_buffer_pos = 0;
b34d6a80 713 if (v && v < sizeof(mdec.block_buffer))
714 mdec.block_buffer_pos = mdec.block_buffer;
8e1040b6 715
716 gzfreeze(&mdec.block_buffer, sizeof(mdec.block_buffer));
717 gzfreeze(&mdec.pending_dma1, sizeof(mdec.pending_dma1));
ef79bbde
P
718 gzfreeze(iq_y, sizeof(iq_y));
719 gzfreeze(iq_uv, sizeof(iq_uv));
720
721 return 0;
722}