//------------------------------------------------------------------------
// 展開
// OnMemory版は#define ONMEM
// 画面アドレスの計算とスーパーバイザーモードへの移行が機種依存

#include "_jpeglib.h"
#include "jpeg.h"
#include "astdio.h"
#include <iocslib.h>

//#define	DEBUG	1
// デバッグモードはx68上でのみ有効
#if DEBUG >=1
#include <stdio.h>
#include <time.h>
#endif

//------------------------------------------------------------------------

static void IDCT0(short *suv,short *sxy,unchar const *Qtable)
// 何もしないダミーのIDCT2と同じ引数の関数
{
}

//------------------------------------------------------------------------

int m(JpegExpand(JDATA(p),int gsx,int gsy,int gwx,int gwy,int ewx,int ewy
	,long mode,short rstcnt
	,unchar *qY,unchar *qU,unchar *qV
	,short y[4][JWY*JWX] ,short u[JWY*JWX] ,short v[JWY*JWX],short suv[JWV*JWU]))
// 展開
// gwx,gwy : 実データサイズ（倍率関係無し）
// ewx,ewy : 展開サイズ（実データサイズにおける展開サイズ；倍率関係無し）
{
#if DEBUG >= 1
time_t ts;
#endif
int sp,gx,gy,i,mcux,mcuy,gmcux,gmcuy,mcu,w; // mcu?は実データのサイズ、gmcu?は表示サイズ
int fbw=0;
unshort *gram,*gram0;
short dcy0=0,dcu0=0,dcv0=0;
short *uu,*vv;
void (*yuv2rgb)(unshort *,short *,short *,short *);
void (*yuv2rgbx)(unshort *,short *,short *,short *,int,int,int);
void (*idcty)(short *,short *,unchar const *);
void (*idcty2)(short *,short *,unchar const *);
void (*idctuv)(short *,short *,unchar const *);
void (*idctuv2)(short *,short *,unchar const *);
static short uv0[JWX*JWY]; // 初期値が全て０のワーク
short RestartCount=rstcnt;
int rst=RST0;
	#if 0
	/////////////////////////////////////////////////////////
	// 不完全ＭＣＵに対応していない時の補正
	gwx=((gwx+7)/8)*8;
	if (mode&(MD_2_11|MD_411)) gwx=((gwx+15)/16)*16;
	gwy=((gwy+7)/8)*8;
	if (mode&(MD_2I11|MD_411)) gwy=((gwy+15)/16)*16;
	/////////////////////////////////////////////////////////
	#endif
	// 展開サイズ補正１
	if (ewx==0||ewx>gwx) ewx=gwx;
	if (ewy==0||ewy>gwy) ewy=gwy;
	
	// モード別設定
	if (mode&MD_BW ) fbw=1; // 白黒モード
	if (mode&MD_BWE) fbw=2; // 白黒展開のみモード
	/*	mcu	mcux	mcuy	yuv2rgb:通常	yuv2rgb:倍率/不完全MCU
	1:1:1	1	JWX	JWY	YUV2RGB1	YUV2RGB1x
	4:1:1	4	JWX*2	JWY*2	YUV2RGB4	YUV2RGB4x
	2-:1:1	2	JWX*2	JWY	YUV2RGB2_	YUV2RGB2_x
	2I:1:1	2	JWX	JWY*2	YUV2RGB2I	YUV2RGB2Ix
	*/
	switch (mode&MD_AMODE) {
		case MD_111: // 1:1:1
			yuv2rgb =YUV2RGB1;	mcux=JWX;	mcuy=JWY;	mcu=1;
			yuv2rgbx=YUV2RGB1x;
			#if DEBUG >=1
			printf("1:1:1 ");
			#endif
			break;
		case MD_411: // 4:1:1
			yuv2rgb =YUV2RGB4;	mcux=JWX*2;	mcuy=JWY*2;	mcu=4;
			yuv2rgbx=YUV2RGB4x;
			#if DEBUG >=1
			printf("4:1:1 ");
			#endif
			break;
		case MD_2I11: // 2I:1:1
			yuv2rgb =YUV2RGB2I;	mcux=JWX;	mcuy=JWY*2;	mcu=2;
			yuv2rgbx=YUV2RGB2Ix;
			#if DEBUG >=1
			printf("2I:1:1 ");
			#endif
			break;
		case MD_2_11: // 2-:1:1
			yuv2rgb=YUV2RGB2_;	mcux=JWX*2;	mcuy=JWY;	mcu=2;
			yuv2rgbx=YUV2RGB2_x;
			#if DEBUG >=1
			printf("2-:1:1 ");
			#endif
			break;
	}
	gmcux=mcux;
	gmcuy=mcuy;
	{
	int ww=1;
	w=1;
	switch (mode&MD_EMODE) {
		case MD_BAIE: // 縦倍
			ww=-1;
			break;
		case MD_1_2E: // 1/2
			ww=2;
			break;
		case MD_1_4E: // 1/4
			ww=4;
			break;
		case MD_1_8E: // 1/8
			ww=8;
			break;
	}
	if (ww>=1) { // 等倍/縮小表示の時
		if (ewx>=ww && ewy>=ww) {
			w=ww;
			gmcux/=w; gmcuy/=w;
			//ewx*=w;  ewy*=w; // 表示可能幅はそれだけ増える
			#if DEBUG >=1
			printf("1/%d展開 ",w);
			#endif
		} // サイズが小さすぎる時は縮小不可（等倍のまま）
		// 展開サイズ補正２：ＧＲＡＭを超える時はカットする
		if (gsx+ewx/w>=X68GWX) ewx=(X68GWX-gsx)*w;
		if (gsy+ewy/w>=X68GWY) ewy=(X68GWY-gsy)*w;
	} else { // 縦倍
		w=ww;
		gmcuy*=2;
		//ewy*=2; // 表示幅も広げてみる
		#if DEBUG >=1
		printf("縦倍展開 ");
		#endif
		// 展開サイズ補正２：ＧＲＡＭを超える時はカットする
		if (gsx+ewx  >=X68GWX) ewx=(X68GWX-gsx)  ;
		if (gsy+ewy*2>=X68GWY) ewy=(X68GWY-gsy)/2;
	}
	}
	
	// バッファーアドレス設定
	uu=u;
	vv=v;
	if (fbw) { // 白黒モード時
		uu=vv=uv0;
	}
	#if DEBUG >= 1
	// モード表示
	{// MCU単位の画像幅を求める
	int gmx,gmy;
	gmx=(gwx/mcux)*mcux;
	gmy=(gwy/mcuy)*mcuy;
	printf("%d*%d=(%d+%d)*(%d+%d)元画像\n",gwx,gwy,gmx,gwx-gmx,gmy,gwy-gmy);
	gmx=(ewx/mcux)*mcux;
	gmy=(ewy/mcuy)*mcuy;
	printf("→%d*%d=(%d+%d)*(%d+%d)展開画像\n",ewx,ewy,gmx,ewx-gmx,gmy,ewy-gmy);
	}
	switch (fbw) {
	    case 1: printf("白黒"); break;
	    case 2: printf("強制白黒"); break;
	}
	printf("展開...");
	ts=clock();
	#endif
	
	// IDCT指定
	idcty=IDCT2;
	idctuv=(fbw==0? IDCT2:IDCT0); // カラー：強制白黒
				      // カラー画像を白黒化する時はU/Vの空読みが必要
	
	gram=GramAdrs(gsx,gsy);
	sp=B_SUPER(0); // スーパーバイザーモードへ
	m(BitInFlush()); // 初期化
	for (gy=0;gy<ewy;gy+=mcuy) {
		#if DEBUG >= 2
		condrv_xoff(); printf("*"); condrv_xon();
		#endif
		idcty2=idcty;
		idctuv2=idctuv;
		gram0=gram;
		for (gx=0;gx<gwx;gx+=mcux) {
			int ret=0;
			if (gx>=ewx) { // 以後ダミー関数にする
				idcty2=IDCT0;
				idctuv2=IDCT0;
			}
			// Y
			for (i=0;i<mcu;i++) {
				ret+=m(iHuffDC(p,iHuffDC_Y,cntDC_Y,suv,&dcy0));
				ret+=m(iHuffAC(p,iHuffAC_Y,cntAC_Y,suv));
				idcty2(suv,&y[i][0],qY);
			}
			if (fbw!=1) { // 白黒でない時
				// U
				ret+=m(iHuffDC(p,iHuffDC_UV,cntDC_UV,suv,&dcu0));
				ret+=m(iHuffAC(p,iHuffAC_UV,cntAC_UV,suv));
				idctuv2(suv,u,qU);
				// V
				ret+=m(iHuffDC(p,iHuffDC_UV,cntDC_UV,suv,&dcv0));
				ret+=m(iHuffAC(p,iHuffAC_UV,cntAC_UV,suv));
				idctuv2(suv,v,qV);
			}
			
			if (rstcnt>0) { // リスタートマーカーが有効な時
			    if (--RestartCount==0) { // リスタート処理
				if (gx+mcux<ewx || gy+mcuy<ewy) {
				    int c;
				    c=m(GetMaker(p));
				    if (c==rst) {
					RestartCount=rstcnt; // カウンタリセット
					dcy0=dcu0=dcv0=0;
					if (++rst>RST7) rst=RST0;
				    } else {
					// リスタートマーカーでない／リスタートマーカーの順序がおかしい
					if (c==EOI) {
						return(1);
					}
					// その他の時は読み飛ばし（厳密にはエラーにした方が良いかも）
				    }
				} // 最終行末は入ってないのでチェックしない
			    }
			}
			
			if (gx<ewx) {
			    // データ書きだし
			    if (gx+mcux>ewx||gy+mcuy>ewy||w!=0) { // 不完全MCU領域/倍率処理あり
				int dx,dy;
				dx=ewx-gx; if (dx>mcux) dx=mcux;
				dy=ewy-gy; if (dy>mcuy) dy=mcuy;
	//	if (gy+mcuy>ewy) {
	//		printf("mcux,mcuy=%d,%d/w=%d/dx,dy=%d,%d\n",mcux,mcuy,w,dx,dy);
	//		getch();
	//	}
				yuv2rgbx(gram,&y[0][0],uu,vv,w,dx,dy);
			    } else { // 完全MCU領域/倍率処理なし
				yuv2rgb(gram,&y[0][0],uu,vv);
			    }
			    gram+=gmcux; // 次のブロックへ
			}
			#ifndef ONMEM
			if (ret) return(ret);
			#endif
		} //  for gx
		// 次のMCUラインへ
		gram=gram0+X68GWX*gmcuy;
	} // for gy
	if (sp>=0) B_SUPER(sp);
	
	#if DEBUG >=1
	printf("\n%d\n",clock()-ts);
	#endif
	
	return(0);
}

//------------------------------------------------------------------------
