summaryrefslogtreecommitdiff
path: root/PcsxSrc/Mdec.c
diff options
context:
space:
mode:
Diffstat (limited to 'PcsxSrc/Mdec.c')
-rw-r--r--PcsxSrc/Mdec.c1174
1 files changed, 587 insertions, 587 deletions
diff --git a/PcsxSrc/Mdec.c b/PcsxSrc/Mdec.c
index 7a6a5c7..cebf285 100644
--- a/PcsxSrc/Mdec.c
+++ b/PcsxSrc/Mdec.c
@@ -1,587 +1,587 @@
-/* Pcsx - Pc Psx Emulator
- * Copyright (C) 1999-2002 Pcsx Team
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-/* This code was based on the FPSE v0.08 Mdec decoder*/
-
-#include <stdio.h>
-#include <string.h>
-
-#include "PsxCommon.h"
-#include "Mdec.h"
-
-#define FIXED
-
-#define CONST_BITS 8
-#define PASS1_BITS 2
-
-#define FIX_1_082392200 (277)
-#define FIX_1_414213562 (362)
-#define FIX_1_847759065 (473)
-#define FIX_2_613125930 (669)
-
-#define MULTIPLY(var,const) (DESCALE((var) * (const), CONST_BITS))
-
-#define DEQUANTIZE(coef,quantval) (coef)
-
-#define DESCALE(x,n) ((x)>>(n))
-#define RANGE(n) (n)
-
-#define DCTSIZE 8
-#define DCTSIZE2 64
-
-static void idct1(int *block)
-{
- int val = RANGE(DESCALE(block[0], PASS1_BITS+3));
- int i;
- for(i=0;i<DCTSIZE2;i++) block[i]=val;
-}
-
-void idct(int *block,int k)
-{
- int tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
- int z5, z10, z11, z12, z13;
- int *ptr;
- int i;
-
- if (!k) { idct1(block); return; }
-
- ptr = block;
- for (i = 0; i< DCTSIZE; i++,ptr++) {
-
- if ((ptr[DCTSIZE*1] | ptr[DCTSIZE*2] | ptr[DCTSIZE*3] |
- ptr[DCTSIZE*4] | ptr[DCTSIZE*5] | ptr[DCTSIZE*6] |
- ptr[DCTSIZE*7]) == 0) {
- ptr[DCTSIZE*0] =
- ptr[DCTSIZE*1] =
- ptr[DCTSIZE*2] =
- ptr[DCTSIZE*3] =
- ptr[DCTSIZE*4] =
- ptr[DCTSIZE*5] =
- ptr[DCTSIZE*6] =
- ptr[DCTSIZE*7] =
- ptr[DCTSIZE*0];
-
- continue;
- }
-
- z10 = ptr[DCTSIZE*0] + ptr[DCTSIZE*4];
- z11 = ptr[DCTSIZE*0] - ptr[DCTSIZE*4];
- z13 = ptr[DCTSIZE*2] + ptr[DCTSIZE*6];
- z12 = MULTIPLY(ptr[DCTSIZE*2] - ptr[DCTSIZE*6], FIX_1_414213562) - z13;
-
- tmp0 = z10 + z13;
- tmp3 = z10 - z13;
- tmp1 = z11 + z12;
- tmp2 = z11 - z12;
-
- z13 = ptr[DCTSIZE*3] + ptr[DCTSIZE*5];
- z10 = ptr[DCTSIZE*3] - ptr[DCTSIZE*5];
- z11 = ptr[DCTSIZE*1] + ptr[DCTSIZE*7];
- z12 = ptr[DCTSIZE*1] - ptr[DCTSIZE*7];
-
- z5 = MULTIPLY(z12 - z10, FIX_1_847759065);
- tmp7 = z11 + z13;
- tmp6 = MULTIPLY(z10, FIX_2_613125930) + z5 - tmp7;
- tmp5 = MULTIPLY(z11 - z13, FIX_1_414213562) - tmp6;
- tmp4 = MULTIPLY(z12, FIX_1_082392200) - z5 + tmp5;
-
- ptr[DCTSIZE*0] = (tmp0 + tmp7);
- ptr[DCTSIZE*7] = (tmp0 - tmp7);
- ptr[DCTSIZE*1] = (tmp1 + tmp6);
- ptr[DCTSIZE*6] = (tmp1 - tmp6);
- ptr[DCTSIZE*2] = (tmp2 + tmp5);
- ptr[DCTSIZE*5] = (tmp2 - tmp5);
- ptr[DCTSIZE*4] = (tmp3 + tmp4);
- ptr[DCTSIZE*3] = (tmp3 - tmp4);
-
- }
-
- ptr = block;
- for (i = 0; i < DCTSIZE; i++ ,ptr+=DCTSIZE) {
-
- if ((ptr[1] | ptr[2] | ptr[3] | ptr[4] | ptr[5] | ptr[6] |
- ptr[7]) == 0) {
- ptr[0] =
- ptr[1] =
- ptr[2] =
- ptr[3] =
- ptr[4] =
- ptr[5] =
- ptr[6] =
- ptr[7] =
- RANGE(DESCALE(ptr[0], PASS1_BITS+3));;
-
- continue;
- }
-
- z10 = ptr[0] + ptr[4];
- z11 = ptr[0] - ptr[4];
- z13 = ptr[2] + ptr[6];
- z12 = MULTIPLY(ptr[2] - ptr[6], FIX_1_414213562) - z13;
-
- tmp0 = z10 + z13;
- tmp3 = z10 - z13;
- tmp1 = z11 + z12;
- tmp2 = z11 - z12;
-
- z13 = ptr[3] + ptr[5];
- z10 = ptr[3] - ptr[5];
- z11 = ptr[1] + ptr[7];
- z12 = ptr[1] - ptr[7];
-
- z5 = MULTIPLY(z12 - z10, FIX_1_847759065);
- tmp7 = z11 + z13;
- tmp6 = MULTIPLY(z10, FIX_2_613125930) + z5 - tmp7;
- tmp5 = MULTIPLY(z11 - z13, FIX_1_414213562) - tmp6;
- tmp4 = MULTIPLY(z12, FIX_1_082392200) - z5 + tmp5;
-
- ptr[0] = RANGE(DESCALE(tmp0 + tmp7, PASS1_BITS+3));;
- ptr[7] = RANGE(DESCALE(tmp0 - tmp7, PASS1_BITS+3));;
- ptr[1] = RANGE(DESCALE(tmp1 + tmp6, PASS1_BITS+3));;
- ptr[6] = RANGE(DESCALE(tmp1 - tmp6, PASS1_BITS+3));;
- ptr[2] = RANGE(DESCALE(tmp2 + tmp5, PASS1_BITS+3));;
- ptr[5] = RANGE(DESCALE(tmp2 - tmp5, PASS1_BITS+3));;
- ptr[4] = RANGE(DESCALE(tmp3 + tmp4, PASS1_BITS+3));;
- ptr[3] = RANGE(DESCALE(tmp3 - tmp4, PASS1_BITS+3));;
-
- }
-}
-
-unsigned short* rl2blk(int *blk,unsigned short *mdec_rl);
-void iqtab_init(int *iqtab,unsigned char *iq_y);
-void round_init(void);
-void yuv2rgb24(int *blk,unsigned char *image);
-void yuv2rgb15(int *blk,unsigned short *image);
-
-struct {
- unsigned long command;
- unsigned long status;
- unsigned short *rl;
- int rlsize;
-} mdec;
-
-int iq_y[DCTSIZE2],iq_uv[DCTSIZE2];
-
-void mdecInit(void) {
- mdec.rl = (u16*)&psxM[0x100000];
- mdec.command = 0;
- mdec.status = 0;
- round_init();
-}
-
-
-void mdecWrite0(u32 data) {
-#ifdef CDR_LOG
- CDR_LOG("mdec0 write %lx\n", data);
-#endif
- mdec.command = data;
- if ((data&0xf5ff0000)==0x30000000) {
- mdec.rlsize = data&0xffff;
- }
-}
-
-void mdecWrite1(u32 data) {
-#ifdef CDR_LOG
- CDR_LOG("mdec1 write %lx\n", data);
-#endif
- if (data&0x80000000) { // mdec reset
- mdec.command = 0;
- mdec.status = 0;
- }
-}
-
-u32 mdecRead0(void) {
-#ifdef CDR_LOG
- CDR_LOG("mdec0 read %lx\n", mdec.command);
-#endif
- return mdec.command;
-}
-
-// mdec status:
-#define MDEC_BUSY 0x20000000
-#define MDEC_DREQ 0x18000000
-#define MDEC_FIFO 0xc0000000
-#define MDEC_RGB24 0x02000000
-#define MDEC_STP 0x00800000
-
-u32 mdecRead1(void) {
-#ifdef CDR_LOG
- CDR_LOG("mdec1 read %lx\n", mdec.status);
-#endif
- return mdec.status;
-}
-
-void psxDma0(u32 adr, u32 bcr, u32 chcr) {
- int cmd = mdec.command;
- int size;
-
-#ifdef CDR_LOG
- CDR_LOG("DMA0 %lx %lx %lx\n", adr, bcr, chcr);
-#endif
-
- if (chcr!=0x01000201) return;
-
- size = (bcr>>16)*(bcr&0xffff);
-
- if (cmd==0x60000000) {
- } else
- if (cmd==0x40000001) {
- u8 *p = (u8*)PSXM(adr);
- iqtab_init(iq_y,p);
- iqtab_init(iq_uv,p+64);
- } else
- if ((cmd&0xf5ff0000)==0x30000000) {
- mdec.rl = (u16*)PSXM(adr);
- }
- else {
- }
-}
-
-void psxDma1(u32 adr, u32 bcr, u32 chcr) {
- int blk[DCTSIZE2*6];
- unsigned short *image;
- int size;
-
-#ifdef CDR_LOG
- CDR_LOG("DMA1 %lx %lx %lx (cmd = %lx)\n", adr, bcr, chcr, mdec.command);
-#endif
-
- if (chcr!=0x01000200) return;
-
- size = (bcr>>16)*(bcr&0xffff);
- image = (u16*)PSXM(adr);
- if (mdec.command&0x08000000) {
- for (;size>0;size-=(16*16)/2,image+=(16*16)) {
- mdec.rl = rl2blk(blk,mdec.rl);
- yuv2rgb15(blk,image);
- }
- } else {
- for (;size>0;size-=(24*16)/2,image+=(24*16)) {
- mdec.rl = rl2blk(blk,mdec.rl);
- yuv2rgb24(blk,(u8 *)image);
- }
- }
-}
-
-
-#define RUNOF(a) ((a)>>10)
-#define VALOF(a) (((int)(a)<<(32-10))>>(32-10))
-
-static int zscan[DCTSIZE2] = {
- 0 ,1 ,8 ,16,9 ,2 ,3 ,10,
- 17,24,32,25,18,11,4 ,5 ,
- 12,19,26,33,40,48,41,34,
- 27,20,13,6 ,7 ,14,21,28,
- 35,42,49,56,57,50,43,36,
- 29,22,15,23,30,37,44,51,
- 58,59,52,45,38,31,39,46,
- 53,60,61,54,47,55,62,63
-};
-
-static int aanscales[DCTSIZE2] = {
- 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
- 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270,
- 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906,
- 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315,
- 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
- 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552,
- 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446,
- 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247
-};
-
-void iqtab_init(int *iqtab,unsigned char *iq_y)
-{
-#define CONST_BITS14 14
-#define IFAST_SCALE_BITS 2
- int i;
-
- for(i=0;i<DCTSIZE2;i++) {
- iqtab[i] =iq_y[i] *aanscales[zscan[i]]>>(CONST_BITS14-IFAST_SCALE_BITS);
- }
-}
-
-/* // From Filefrmt.pdf
-
- RL data syntax:
- header
- macroblock
- ...
- macroblock
- footer
-
- header:
- 16bit: magic (0x3800)
- 16bit: size
-
- macroblock:
- Cb block
- Cr block
- Y1 block
- Y2 block
- Y3 block
- Y4 block
-
- block:
- 5bit: quant, 10bit: dc
- 5bit: run, 10bit: level
- ...
- 5bit: run, 10bit: level
- nop (0xfe00)
-
- footer:
- nop
-
- block conversion:
- zigzag -> dequantize -> idct -> yuv2rgb
-
- zigzag transformation:
-
- the blk_zig value is the level value of the block
-
- blk_zig[0] = blk_dct[0]/iq_tab[0];
- for (i = 1; i < 64; i++) {
- j = zscan[i];
- blk_zig[i] = blk_dct[j]*16/(iqtab[j]*q_scale);
- }
-
- reverse it:
- blk_dct[0] = blk_zig[0]*iq_tab[0];
- for (i = 1; i < 64; i++) {
- j = zscan[i];
- blk_dct[j] = blk_zig[i]/(16/(iqtab[j]*q_scale));
- }
-
- (run, level) (the number of zeros preceding level, value of the element)
-
- run-level example:
- -229 -19 0 -2 0 0 1 0
- (0,-229) (0,-19) (1,-2) (2,1) nop
-
- dequantization:
-
- quant = q_scale
-
- y[0] = x[0] * 16 / (iqtab[0] * 8);
- for (i = 1; i < 64; i++)
- y[i] = x[i] / (quant * Qtable[i]);
-
- reverse it:
- x[0] = y[0] / (16 / (iqtab[0] * 8));
- for (i = 1; i < 64; i++)
- x[i] = y[i] * (quant * Qtable[i]);
-
- idct:
-
- yuv2rgb:
-
- R = Y * 1.0 + Cb * 0 + Cr * 1.402
- G = Y * 1.0 + Cb * -0.3437 + Cr * -0.7143
- B = Y * 1.0 + Cb * 1.772 + Cr * 0
-*/
-#define NOP 0xfe00
-unsigned short* rl2blk(int *blk,unsigned short *mdec_rl) {
- int i,k,q_scale,rl;
- int *iqtab;
-
- memset (blk, 0, 6*DCTSIZE2*4);
- iqtab = iq_uv;
- for(i=0;i<6;i++) { // decode blocks (Cr,Cb,Y1,Y2,Y3,Y4)
- if (i>1) iqtab = iq_y;
-
- // zigzag transformation
- rl = *mdec_rl++;
- q_scale = RUNOF(rl);
- blk[0] = iqtab[0]*VALOF(rl);
- for(k = 0;;) {
- rl = *mdec_rl++;
- if (rl==NOP) break;
- k += RUNOF(rl)+1; // skip level zero-coefficients
- if (k > 63) break;
- blk[zscan[k]] = (VALOF(rl) * iqtab[k] * q_scale) / 8; // / 16;
- }
-// blk[0] = (blk[0] * iq_t[0] * 8) / 16;
-// for(int j=1;j<64;j++)
-// blk[j] = blk[j] * iq_t[j] * q_scale;
-
- // idct
- idct(blk,k+1);
-
- blk+=DCTSIZE2;
- }
- return mdec_rl;
-}
-
-#ifdef FIXED
-#define MULR(a) ((((int)0x0000059B) * (a)) >> 10)
-#define MULG(a) ((((int)0xFFFFFEA1) * (a)) >> 10)
-#define MULG2(a) ((((int)0xFFFFFD25) * (a)) >> 10)
-#define MULB(a) ((((int)0x00000716) * (a)) >> 10)
-#else
-#define MULR(a) ((int)((float)1.40200 * (a)))
-#define MULG(a) ((int)((float)-0.3437 * (a)))
-#define MULG2(a) ((int)((float)-0.7143 * (a)))
-#define MULB(a) ((int)((float)1.77200 * (a)))
-#endif
-
-#define MAKERGB15(r,g,b) ( (((r)>>3)<<10)|(((g)>>3)<<5)|((b)>>3) )
-#define ROUND(c) roundtbl[((c)+128+256)]//&0x3ff]
-/*#define ROUND(c) round(c+128)
-int round(int r) {
- if (r<0) return 0;
- if (r>255) return 255;
- return r;
-}*/
-
-#define RGB15(n, Y) \
- image[n] = MAKERGB15(ROUND(Y + R),ROUND(Y + G),ROUND(Y + B));
-
-#define RGB15BW(n, Y) \
- image[n] = MAKERGB15(ROUND(Y),ROUND(Y),ROUND(Y));
-
-#define RGB24(n, Y) \
- image[n+2] = ROUND(Y + R); \
- image[n+1] = ROUND(Y + G); \
- image[n+0] = ROUND(Y + B);
-
-#define RGB24BW(n, Y) \
- image[n+2] = ROUND(Y); \
- image[n+1] = ROUND(Y); \
- image[n+0] = ROUND(Y);
-
-unsigned char roundtbl[256*3];
-
-void round_init(void) {
- int i;
- for(i=0;i<256;i++) {
- roundtbl[i]=0;
- roundtbl[i+256]=i;
- roundtbl[i+512]=255;
- }
-}
-
-void yuv2rgb15(int *blk,unsigned short *image) {
- int x,y;
- int *Yblk = blk+DCTSIZE2*2;
- int Cb,Cr,R,G,B;
- int *Cbblk = blk;
- int *Crblk = blk+DCTSIZE2;
-
- if (!(Config.Mdec&0x1))
- for (y=0;y<16;y+=2,Crblk+=4,Cbblk+=4,Yblk+=8,image+=24) {
- if (y==8) Yblk+=DCTSIZE2;
- for (x=0;x<4;x++,image+=2,Crblk++,Cbblk++,Yblk+=2) {
- Cr = *Crblk;
- Cb = *Cbblk;
- R = MULR(Cr);
- G = MULG(Cb) + MULG2(Cr);
- B = MULB(Cb);
-
- RGB15(0, Yblk[0]);
- RGB15(1, Yblk[1]);
- RGB15(16, Yblk[8]);
- RGB15(17, Yblk[9]);
-
- Cr = *(Crblk+4);
- Cb = *(Cbblk+4);
- R = MULR(Cr);
- G = MULG(Cb) + MULG2(Cr);
- B = MULB(Cb);
-
- RGB15(8, Yblk[DCTSIZE2+0]);
- RGB15(9, Yblk[DCTSIZE2+1]);
- RGB15(24, Yblk[DCTSIZE2+8]);
- RGB15(25, Yblk[DCTSIZE2+9]);
- }
- } else
- for (y=0;y<16;y+=2,Yblk+=8,image+=24) {
- if (y==8) Yblk+=DCTSIZE2;
- for (x=0;x<4;x++,image+=2,Yblk+=2) {
- RGB15BW(0, Yblk[0]);
- RGB15BW(1, Yblk[1]);
- RGB15BW(16, Yblk[8]);
- RGB15BW(17, Yblk[9]);
-
- RGB15BW(8, Yblk[DCTSIZE2+0]);
- RGB15BW(9, Yblk[DCTSIZE2+1]);
- RGB15BW(24, Yblk[DCTSIZE2+8]);
- RGB15BW(25, Yblk[DCTSIZE2+9]);
- }
- }
-}
-
-void yuv2rgb24(int *blk,unsigned char *image) {
- int x,y;
- int *Yblk = blk+DCTSIZE2*2;
- int Cb,Cr,R,G,B;
- int *Cbblk = blk;
- int *Crblk = blk+DCTSIZE2;
-
- if (!(Config.Mdec&0x1))
- for (y=0;y<16;y+=2,Crblk+=4,Cbblk+=4,Yblk+=8,image+=24*3) {
- if (y==8) Yblk+=DCTSIZE2;
- for (x=0;x<4;x++,image+=6,Crblk++,Cbblk++,Yblk+=2) {
- Cr = *Crblk;
- Cb = *Cbblk;
- R = MULR(Cr);
- G = MULG(Cb) + MULG2(Cr);
- B = MULB(Cb);
-
- RGB24(0, Yblk[0]);
- RGB24(1*3, Yblk[1]);
- RGB24(16*3, Yblk[8]);
- RGB24(17*3, Yblk[9]);
-
- Cr = *(Crblk+4);
- Cb = *(Cbblk+4);
- R = MULR(Cr);
- G = MULG(Cb) + MULG2(Cr);
- B = MULB(Cb);
-
- RGB24(8*3, Yblk[DCTSIZE2+0]);
- RGB24(9*3, Yblk[DCTSIZE2+1]);
- RGB24(24*3, Yblk[DCTSIZE2+8]);
- RGB24(25*3, Yblk[DCTSIZE2+9]);
- }
- } else
- for (y=0;y<16;y+=2,Yblk+=8,image+=24*3) {
- if (y==8) Yblk+=DCTSIZE2;
- for (x=0;x<4;x++,image+=6,Yblk+=2) {
- RGB24BW(0, Yblk[0]);
- RGB24BW(1*3, Yblk[1]);
- RGB24BW(16*3, Yblk[8]);
- RGB24BW(17*3, Yblk[9]);
-
- RGB24BW(8*3, Yblk[DCTSIZE2+0]);
- RGB24BW(9*3, Yblk[DCTSIZE2+1]);
- RGB24BW(24*3, Yblk[DCTSIZE2+8]);
- RGB24BW(25*3, Yblk[DCTSIZE2+9]);
- }
- }
-}
-
-int mdecFreeze(gzFile f, int Mode) {
- char Unused[4096];
-
- gzfreeze(&mdec, sizeof(mdec));
- gzfreezel(iq_y);
- gzfreezel(iq_uv);
- gzfreezel(Unused);
-
- return 0;
-}
-
+/* Pcsx - Pc Psx Emulator
+ * Copyright (C) 1999-2002 Pcsx Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* This code was based on the FPSE v0.08 Mdec decoder*/
+
+#include <stdio.h>
+#include <string.h>
+
+#include "PsxCommon.h"
+#include "Mdec.h"
+
+#define FIXED
+
+#define CONST_BITS 8
+#define PASS1_BITS 2
+
+#define FIX_1_082392200 (277)
+#define FIX_1_414213562 (362)
+#define FIX_1_847759065 (473)
+#define FIX_2_613125930 (669)
+
+#define MULTIPLY(var,const) (DESCALE((var) * (const), CONST_BITS))
+
+#define DEQUANTIZE(coef,quantval) (coef)
+
+#define DESCALE(x,n) ((x)>>(n))
+#define RANGE(n) (n)
+
+#define DCTSIZE 8
+#define DCTSIZE2 64
+
+static void idct1(int *block)
+{
+ int val = RANGE(DESCALE(block[0], PASS1_BITS+3));
+ int i;
+ for(i=0;i<DCTSIZE2;i++) block[i]=val;
+}
+
+void idct(int *block,int k)
+{
+ int tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ int z5, z10, z11, z12, z13;
+ int *ptr;
+ int i;
+
+ if (!k) { idct1(block); return; }
+
+ ptr = block;
+ for (i = 0; i< DCTSIZE; i++,ptr++) {
+
+ if ((ptr[DCTSIZE*1] | ptr[DCTSIZE*2] | ptr[DCTSIZE*3] |
+ ptr[DCTSIZE*4] | ptr[DCTSIZE*5] | ptr[DCTSIZE*6] |
+ ptr[DCTSIZE*7]) == 0) {
+ ptr[DCTSIZE*0] =
+ ptr[DCTSIZE*1] =
+ ptr[DCTSIZE*2] =
+ ptr[DCTSIZE*3] =
+ ptr[DCTSIZE*4] =
+ ptr[DCTSIZE*5] =
+ ptr[DCTSIZE*6] =
+ ptr[DCTSIZE*7] =
+ ptr[DCTSIZE*0];
+
+ continue;
+ }
+
+ z10 = ptr[DCTSIZE*0] + ptr[DCTSIZE*4];
+ z11 = ptr[DCTSIZE*0] - ptr[DCTSIZE*4];
+ z13 = ptr[DCTSIZE*2] + ptr[DCTSIZE*6];
+ z12 = MULTIPLY(ptr[DCTSIZE*2] - ptr[DCTSIZE*6], FIX_1_414213562) - z13;
+
+ tmp0 = z10 + z13;
+ tmp3 = z10 - z13;
+ tmp1 = z11 + z12;
+ tmp2 = z11 - z12;
+
+ z13 = ptr[DCTSIZE*3] + ptr[DCTSIZE*5];
+ z10 = ptr[DCTSIZE*3] - ptr[DCTSIZE*5];
+ z11 = ptr[DCTSIZE*1] + ptr[DCTSIZE*7];
+ z12 = ptr[DCTSIZE*1] - ptr[DCTSIZE*7];
+
+ z5 = MULTIPLY(z12 - z10, FIX_1_847759065);
+ tmp7 = z11 + z13;
+ tmp6 = MULTIPLY(z10, FIX_2_613125930) + z5 - tmp7;
+ tmp5 = MULTIPLY(z11 - z13, FIX_1_414213562) - tmp6;
+ tmp4 = MULTIPLY(z12, FIX_1_082392200) - z5 + tmp5;
+
+ ptr[DCTSIZE*0] = (tmp0 + tmp7);
+ ptr[DCTSIZE*7] = (tmp0 - tmp7);
+ ptr[DCTSIZE*1] = (tmp1 + tmp6);
+ ptr[DCTSIZE*6] = (tmp1 - tmp6);
+ ptr[DCTSIZE*2] = (tmp2 + tmp5);
+ ptr[DCTSIZE*5] = (tmp2 - tmp5);
+ ptr[DCTSIZE*4] = (tmp3 + tmp4);
+ ptr[DCTSIZE*3] = (tmp3 - tmp4);
+
+ }
+
+ ptr = block;
+ for (i = 0; i < DCTSIZE; i++ ,ptr+=DCTSIZE) {
+
+ if ((ptr[1] | ptr[2] | ptr[3] | ptr[4] | ptr[5] | ptr[6] |
+ ptr[7]) == 0) {
+ ptr[0] =
+ ptr[1] =
+ ptr[2] =
+ ptr[3] =
+ ptr[4] =
+ ptr[5] =
+ ptr[6] =
+ ptr[7] =
+ RANGE(DESCALE(ptr[0], PASS1_BITS+3));;
+
+ continue;
+ }
+
+ z10 = ptr[0] + ptr[4];
+ z11 = ptr[0] - ptr[4];
+ z13 = ptr[2] + ptr[6];
+ z12 = MULTIPLY(ptr[2] - ptr[6], FIX_1_414213562) - z13;
+
+ tmp0 = z10 + z13;
+ tmp3 = z10 - z13;
+ tmp1 = z11 + z12;
+ tmp2 = z11 - z12;
+
+ z13 = ptr[3] + ptr[5];
+ z10 = ptr[3] - ptr[5];
+ z11 = ptr[1] + ptr[7];
+ z12 = ptr[1] - ptr[7];
+
+ z5 = MULTIPLY(z12 - z10, FIX_1_847759065);
+ tmp7 = z11 + z13;
+ tmp6 = MULTIPLY(z10, FIX_2_613125930) + z5 - tmp7;
+ tmp5 = MULTIPLY(z11 - z13, FIX_1_414213562) - tmp6;
+ tmp4 = MULTIPLY(z12, FIX_1_082392200) - z5 + tmp5;
+
+ ptr[0] = RANGE(DESCALE(tmp0 + tmp7, PASS1_BITS+3));;
+ ptr[7] = RANGE(DESCALE(tmp0 - tmp7, PASS1_BITS+3));;
+ ptr[1] = RANGE(DESCALE(tmp1 + tmp6, PASS1_BITS+3));;
+ ptr[6] = RANGE(DESCALE(tmp1 - tmp6, PASS1_BITS+3));;
+ ptr[2] = RANGE(DESCALE(tmp2 + tmp5, PASS1_BITS+3));;
+ ptr[5] = RANGE(DESCALE(tmp2 - tmp5, PASS1_BITS+3));;
+ ptr[4] = RANGE(DESCALE(tmp3 + tmp4, PASS1_BITS+3));;
+ ptr[3] = RANGE(DESCALE(tmp3 - tmp4, PASS1_BITS+3));;
+
+ }
+}
+
+unsigned short* rl2blk(int *blk,unsigned short *mdec_rl);
+void iqtab_init(int *iqtab,unsigned char *iq_y);
+void round_init(void);
+void yuv2rgb24(int *blk,unsigned char *image);
+void yuv2rgb15(int *blk,unsigned short *image);
+
+struct {
+ unsigned long command;
+ unsigned long status;
+ unsigned short *rl;
+ int rlsize;
+} mdec;
+
+int iq_y[DCTSIZE2],iq_uv[DCTSIZE2];
+
+void mdecInit(void) {
+ mdec.rl = (u16*)&psxM[0x100000];
+ mdec.command = 0;
+ mdec.status = 0;
+ round_init();
+}
+
+
+void mdecWrite0(u32 data) {
+#ifdef CDR_LOG
+ CDR_LOG("mdec0 write %lx\n", data);
+#endif
+ mdec.command = data;
+ if ((data&0xf5ff0000)==0x30000000) {
+ mdec.rlsize = data&0xffff;
+ }
+}
+
+void mdecWrite1(u32 data) {
+#ifdef CDR_LOG
+ CDR_LOG("mdec1 write %lx\n", data);
+#endif
+ if (data&0x80000000) { // mdec reset
+ mdec.command = 0;
+ mdec.status = 0;
+ }
+}
+
+u32 mdecRead0(void) {
+#ifdef CDR_LOG
+ CDR_LOG("mdec0 read %lx\n", mdec.command);
+#endif
+ return mdec.command;
+}
+
+// mdec status:
+#define MDEC_BUSY 0x20000000
+#define MDEC_DREQ 0x18000000
+#define MDEC_FIFO 0xc0000000
+#define MDEC_RGB24 0x02000000
+#define MDEC_STP 0x00800000
+
+u32 mdecRead1(void) {
+#ifdef CDR_LOG
+ CDR_LOG("mdec1 read %lx\n", mdec.status);
+#endif
+ return mdec.status;
+}
+
+void psxDma0(u32 adr, u32 bcr, u32 chcr) {
+ int cmd = mdec.command;
+ int size;
+
+#ifdef CDR_LOG
+ CDR_LOG("DMA0 %lx %lx %lx\n", adr, bcr, chcr);
+#endif
+
+ if (chcr!=0x01000201) return;
+
+ size = (bcr>>16)*(bcr&0xffff);
+
+ if (cmd==0x60000000) {
+ } else
+ if (cmd==0x40000001) {
+ u8 *p = (u8*)PSXM(adr);
+ iqtab_init(iq_y,p);
+ iqtab_init(iq_uv,p+64);
+ } else
+ if ((cmd&0xf5ff0000)==0x30000000) {
+ mdec.rl = (u16*)PSXM(adr);
+ }
+ else {
+ }
+}
+
+void psxDma1(u32 adr, u32 bcr, u32 chcr) {
+ int blk[DCTSIZE2*6];
+ unsigned short *image;
+ int size;
+
+#ifdef CDR_LOG
+ CDR_LOG("DMA1 %lx %lx %lx (cmd = %lx)\n", adr, bcr, chcr, mdec.command);
+#endif
+
+ if (chcr!=0x01000200) return;
+
+ size = (bcr>>16)*(bcr&0xffff);
+ image = (u16*)PSXM(adr);
+ if (mdec.command&0x08000000) {
+ for (;size>0;size-=(16*16)/2,image+=(16*16)) {
+ mdec.rl = rl2blk(blk,mdec.rl);
+ yuv2rgb15(blk,image);
+ }
+ } else {
+ for (;size>0;size-=(24*16)/2,image+=(24*16)) {
+ mdec.rl = rl2blk(blk,mdec.rl);
+ yuv2rgb24(blk,(u8 *)image);
+ }
+ }
+}
+
+
+#define RUNOF(a) ((a)>>10)
+#define VALOF(a) (((int)(a)<<(32-10))>>(32-10))
+
+static int zscan[DCTSIZE2] = {
+ 0 ,1 ,8 ,16,9 ,2 ,3 ,10,
+ 17,24,32,25,18,11,4 ,5 ,
+ 12,19,26,33,40,48,41,34,
+ 27,20,13,6 ,7 ,14,21,28,
+ 35,42,49,56,57,50,43,36,
+ 29,22,15,23,30,37,44,51,
+ 58,59,52,45,38,31,39,46,
+ 53,60,61,54,47,55,62,63
+};
+
+static int aanscales[DCTSIZE2] = {
+ 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
+ 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270,
+ 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906,
+ 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315,
+ 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
+ 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552,
+ 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446,
+ 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247
+};
+
+void iqtab_init(int *iqtab,unsigned char *iq_y)
+{
+#define CONST_BITS14 14
+#define IFAST_SCALE_BITS 2
+ int i;
+
+ for(i=0;i<DCTSIZE2;i++) {
+ iqtab[i] =iq_y[i] *aanscales[zscan[i]]>>(CONST_BITS14-IFAST_SCALE_BITS);
+ }
+}
+
+/* // From Filefrmt.pdf
+
+ RL data syntax:
+ header
+ macroblock
+ ...
+ macroblock
+ footer
+
+ header:
+ 16bit: magic (0x3800)
+ 16bit: size
+
+ macroblock:
+ Cb block
+ Cr block
+ Y1 block
+ Y2 block
+ Y3 block
+ Y4 block
+
+ block:
+ 5bit: quant, 10bit: dc
+ 5bit: run, 10bit: level
+ ...
+ 5bit: run, 10bit: level
+ nop (0xfe00)
+
+ footer:
+ nop
+
+ block conversion:
+ zigzag -> dequantize -> idct -> yuv2rgb
+
+ zigzag transformation:
+
+ the blk_zig value is the level value of the block
+
+ blk_zig[0] = blk_dct[0]/iq_tab[0];
+ for (i = 1; i < 64; i++) {
+ j = zscan[i];
+ blk_zig[i] = blk_dct[j]*16/(iqtab[j]*q_scale);
+ }
+
+ reverse it:
+ blk_dct[0] = blk_zig[0]*iq_tab[0];
+ for (i = 1; i < 64; i++) {
+ j = zscan[i];
+ blk_dct[j] = blk_zig[i]/(16/(iqtab[j]*q_scale));
+ }
+
+ (run, level) (the number of zeros preceding level, value of the element)
+
+ run-level example:
+ -229 -19 0 -2 0 0 1 0
+ (0,-229) (0,-19) (1,-2) (2,1) nop
+
+ dequantization:
+
+ quant = q_scale
+
+ y[0] = x[0] * 16 / (iqtab[0] * 8);
+ for (i = 1; i < 64; i++)
+ y[i] = x[i] / (quant * Qtable[i]);
+
+ reverse it:
+ x[0] = y[0] / (16 / (iqtab[0] * 8));
+ for (i = 1; i < 64; i++)
+ x[i] = y[i] * (quant * Qtable[i]);
+
+ idct:
+
+ yuv2rgb:
+
+ R = Y * 1.0 + Cb * 0 + Cr * 1.402
+ G = Y * 1.0 + Cb * -0.3437 + Cr * -0.7143
+ B = Y * 1.0 + Cb * 1.772 + Cr * 0
+*/
+#define NOP 0xfe00
+unsigned short* rl2blk(int *blk,unsigned short *mdec_rl) {
+ int i,k,q_scale,rl;
+ int *iqtab;
+
+ memset (blk, 0, 6*DCTSIZE2*4);
+ iqtab = iq_uv;
+ for(i=0;i<6;i++) { // decode blocks (Cr,Cb,Y1,Y2,Y3,Y4)
+ if (i>1) iqtab = iq_y;
+
+ // zigzag transformation
+ rl = *mdec_rl++;
+ q_scale = RUNOF(rl);
+ blk[0] = iqtab[0]*VALOF(rl);
+ for(k = 0;;) {
+ rl = *mdec_rl++;
+ if (rl==NOP) break;
+ k += RUNOF(rl)+1; // skip level zero-coefficients
+ if (k > 63) break;
+ blk[zscan[k]] = (VALOF(rl) * iqtab[k] * q_scale) / 8; // / 16;
+ }
+// blk[0] = (blk[0] * iq_t[0] * 8) / 16;
+// for(int j=1;j<64;j++)
+// blk[j] = blk[j] * iq_t[j] * q_scale;
+
+ // idct
+ idct(blk,k+1);
+
+ blk+=DCTSIZE2;
+ }
+ return mdec_rl;
+}
+
+#ifdef FIXED
+#define MULR(a) ((((int)0x0000059B) * (a)) >> 10)
+#define MULG(a) ((((int)0xFFFFFEA1) * (a)) >> 10)
+#define MULG2(a) ((((int)0xFFFFFD25) * (a)) >> 10)
+#define MULB(a) ((((int)0x00000716) * (a)) >> 10)
+#else
+#define MULR(a) ((int)((float)1.40200 * (a)))
+#define MULG(a) ((int)((float)-0.3437 * (a)))
+#define MULG2(a) ((int)((float)-0.7143 * (a)))
+#define MULB(a) ((int)((float)1.77200 * (a)))
+#endif
+
+#define MAKERGB15(r,g,b) ( (((r)>>3)<<10)|(((g)>>3)<<5)|((b)>>3) )
+#define ROUND(c) roundtbl[((c)+128+256)]//&0x3ff]
+/*#define ROUND(c) round(c+128)
+int round(int r) {
+ if (r<0) return 0;
+ if (r>255) return 255;
+ return r;
+}*/
+
+#define RGB15(n, Y) \
+ image[n] = MAKERGB15(ROUND(Y + R),ROUND(Y + G),ROUND(Y + B));
+
+#define RGB15BW(n, Y) \
+ image[n] = MAKERGB15(ROUND(Y),ROUND(Y),ROUND(Y));
+
+#define RGB24(n, Y) \
+ image[n+2] = ROUND(Y + R); \
+ image[n+1] = ROUND(Y + G); \
+ image[n+0] = ROUND(Y + B);
+
+#define RGB24BW(n, Y) \
+ image[n+2] = ROUND(Y); \
+ image[n+1] = ROUND(Y); \
+ image[n+0] = ROUND(Y);
+
+unsigned char roundtbl[256*3];
+
+void round_init(void) {
+ int i;
+ for(i=0;i<256;i++) {
+ roundtbl[i]=0;
+ roundtbl[i+256]=i;
+ roundtbl[i+512]=255;
+ }
+}
+
+void yuv2rgb15(int *blk,unsigned short *image) {
+ int x,y;
+ int *Yblk = blk+DCTSIZE2*2;
+ int Cb,Cr,R,G,B;
+ int *Cbblk = blk;
+ int *Crblk = blk+DCTSIZE2;
+
+ if (!(Config.Mdec&0x1))
+ for (y=0;y<16;y+=2,Crblk+=4,Cbblk+=4,Yblk+=8,image+=24) {
+ if (y==8) Yblk+=DCTSIZE2;
+ for (x=0;x<4;x++,image+=2,Crblk++,Cbblk++,Yblk+=2) {
+ Cr = *Crblk;
+ Cb = *Cbblk;
+ R = MULR(Cr);
+ G = MULG(Cb) + MULG2(Cr);
+ B = MULB(Cb);
+
+ RGB15(0, Yblk[0]);
+ RGB15(1, Yblk[1]);
+ RGB15(16, Yblk[8]);
+ RGB15(17, Yblk[9]);
+
+ Cr = *(Crblk+4);
+ Cb = *(Cbblk+4);
+ R = MULR(Cr);
+ G = MULG(Cb) + MULG2(Cr);
+ B = MULB(Cb);
+
+ RGB15(8, Yblk[DCTSIZE2+0]);
+ RGB15(9, Yblk[DCTSIZE2+1]);
+ RGB15(24, Yblk[DCTSIZE2+8]);
+ RGB15(25, Yblk[DCTSIZE2+9]);
+ }
+ } else
+ for (y=0;y<16;y+=2,Yblk+=8,image+=24) {
+ if (y==8) Yblk+=DCTSIZE2;
+ for (x=0;x<4;x++,image+=2,Yblk+=2) {
+ RGB15BW(0, Yblk[0]);
+ RGB15BW(1, Yblk[1]);
+ RGB15BW(16, Yblk[8]);
+ RGB15BW(17, Yblk[9]);
+
+ RGB15BW(8, Yblk[DCTSIZE2+0]);
+ RGB15BW(9, Yblk[DCTSIZE2+1]);
+ RGB15BW(24, Yblk[DCTSIZE2+8]);
+ RGB15BW(25, Yblk[DCTSIZE2+9]);
+ }
+ }
+}
+
+void yuv2rgb24(int *blk,unsigned char *image) {
+ int x,y;
+ int *Yblk = blk+DCTSIZE2*2;
+ int Cb,Cr,R,G,B;
+ int *Cbblk = blk;
+ int *Crblk = blk+DCTSIZE2;
+
+ if (!(Config.Mdec&0x1))
+ for (y=0;y<16;y+=2,Crblk+=4,Cbblk+=4,Yblk+=8,image+=24*3) {
+ if (y==8) Yblk+=DCTSIZE2;
+ for (x=0;x<4;x++,image+=6,Crblk++,Cbblk++,Yblk+=2) {
+ Cr = *Crblk;
+ Cb = *Cbblk;
+ R = MULR(Cr);
+ G = MULG(Cb) + MULG2(Cr);
+ B = MULB(Cb);
+
+ RGB24(0, Yblk[0]);
+ RGB24(1*3, Yblk[1]);
+ RGB24(16*3, Yblk[8]);
+ RGB24(17*3, Yblk[9]);
+
+ Cr = *(Crblk+4);
+ Cb = *(Cbblk+4);
+ R = MULR(Cr);
+ G = MULG(Cb) + MULG2(Cr);
+ B = MULB(Cb);
+
+ RGB24(8*3, Yblk[DCTSIZE2+0]);
+ RGB24(9*3, Yblk[DCTSIZE2+1]);
+ RGB24(24*3, Yblk[DCTSIZE2+8]);
+ RGB24(25*3, Yblk[DCTSIZE2+9]);
+ }
+ } else
+ for (y=0;y<16;y+=2,Yblk+=8,image+=24*3) {
+ if (y==8) Yblk+=DCTSIZE2;
+ for (x=0;x<4;x++,image+=6,Yblk+=2) {
+ RGB24BW(0, Yblk[0]);
+ RGB24BW(1*3, Yblk[1]);
+ RGB24BW(16*3, Yblk[8]);
+ RGB24BW(17*3, Yblk[9]);
+
+ RGB24BW(8*3, Yblk[DCTSIZE2+0]);
+ RGB24BW(9*3, Yblk[DCTSIZE2+1]);
+ RGB24BW(24*3, Yblk[DCTSIZE2+8]);
+ RGB24BW(25*3, Yblk[DCTSIZE2+9]);
+ }
+ }
+}
+
+int mdecFreeze(gzFile f, int Mode) {
+ char Unused[4096];
+
+ gzfreeze(&mdec, sizeof(mdec));
+ gzfreezel(iq_y);
+ gzfreezel(iq_uv);
+ gzfreezel(Unused);
+
+ return 0;
+}
+