/*****************************************************************************/
/* ＺＩＭファイル表示 */
/*****************************************************************************/

#include <stdio.h>
#include <string.h>
#include "defines.h"
#include "aig.h"

/*****************************************************************************/

int zim_disp(FILE *fp,int fnonclr,int fofmem)
/* ZIM表示（PRO/XVI/98/FM-R全対応,ライブラリ対応,パレット対応,圧縮対応）*/
{
unchar exbuff[512/8*16],work[512/8*16];
unchar head[506+2],*buff;
int x,y,wx,mode,len,fpress;
void (*func)();
extern void zim1disp(),zim1disp16(),rzim1disp16();
	/* ファイル先頭へ戻す：ヘッダー確認のため読み出されているから */
	rewind(fp);
	
	/* マッチストリングチェック */
	if (fread(head,16,1,fp)==0) return(1);
	if (memcmp(head,"FORMAT-A",8)) return(2); /* ZIMファイルではない */
	
	/* 第１固定ヘッダー読み出し */
	if (fread(head,490+2,1,fp)==0) return(1);
	
	mode=ctol80(&head[22]); /* 1=PRO,3=XVI/PC98,4=FM-R50 */
	
	/* １ライン表示関数設定 */
	func=rzim1disp16; /* 98/FM-R50 */
	if (strcmpi(&head[90],"Z'sSTAFF PRO68k")==0) func=zim1disp;   /* PRO */
	if (strcmpi(&head[90],"Z'sSTAFF XVI68k")==0) func=zim1disp16; /* XVI */
	
	/* リザーブエリアスキップ (words) */
	fseek(fp,ctos80(&head[490])*2,SEEK_CUR);
	
	/* 第２固定ヘッダー読み出し */
	if (fread(head,28,1,fp)==0) return(1);
	
	/* 圧縮フラグチェック */
	fpress=ctos80(&head[24]);
	
	/* 画面初期化 */
	/* mode=1:512*512:65536 , =3,4:768*512:16 */
	if (!fnonclr || CRTMOD(-1)!=(mode==1? 12:16)) {
		if (mode==1) screen(1,3,1,1); else screen(2,0,1,1);
	}
	
	/* アナログパレット */
	if (ctos80(&head[26])) {
		unchar *pal;
		/* パレット読み出し */
		if (fread(head,64,1,fp)==0) return(1);
		pal=head;
		for (x=0;x<16;x++) {
			y=x*2;
			if (x>=8) y=(x-8)*2+1;
			palet(y,rgb(*(pal+1)/8,*(pal+2)/8,*pal/8));
			pal+=4;
		}
	}
	
	/* リザーブ領域スキップ */
	if (fread(head,2,1,fp)==0) return(1);
	fseek(fp,ctos80(head)*2,SEEK_CUR);
	
	/* 読み込みバッファー確保 */
	if (!fofmem) {
		x=filelength(fileno(fp))-ftell(fp);
		if (x<=0) return(3);
		buff=newmalloc(x);
	} else buff=NULL;
	
	/* 表示 */
	/* 現在ＸＶＩの任意形状ライブラリ出力は使えないが、ここでは対応している */
	if (buff!=NULL) { /* バッファーがとれる時 */
		unchar *buff2;
		if (fread(buff,x,1,fp)==0) { /* いっぺんに全部読み込む */
			free(buff);
			return(1);
		}
		buff2=buff; /* buffを変更するので退避しておく */
		if (fpress) { /* 圧縮 */
			while ((wx=ctos80(buff))!=0) {
				x=ctos80(&buff[2]);
				y=ctos80(&buff[4]);
				len=ctos80(&buff[6]); /* 圧縮データバイト数 */
				buff+=8;
				if (y<512) {
					zim_expand(buff,exbuff,work,len);
					func(x,y,exbuff,wx);
				}
				buff+=len;
			}
		} else { /* 非圧縮 */
			while ((wx=ctos80(buff))!=0) {
				x=ctos80(&buff[2]);
				y=ctos80(&buff[4]);
				buff+=6;
				if (y<512) func(x,y,buff,wx);
				buff+=((wx+7)/8*(mode==1? 16:4));
			}
		}
		free(buff2);
	} else { /* 一気に読み込むバッファーがとれない時 */
		unchar line[512/8*16]; /* PRO用:XVIは[768/8*4]だが、PRO用の方が大きいのでそれを使う */
		if (fpress) { /* 圧縮 */
			while (1) {
				/* read header */
				if (fread(head,6,1,fp)==0) return(1);
				if ((wx=ctos80(head))==0) break; /* end of data */
				x=ctos80(&buff[2]);
				y=ctos80(&buff[4]);
				if (fread(head,2,1,fp)==0) return(1);
				len=ctos80(buff); /* 圧縮データバイト数 */
				/* read line data */
				if (fread(line,len,1,fp)==0) return(1);
				if (y<512) {
					zim_expand(line,exbuff,work,len);
					func(x,y,exbuff,wx);
				}
			}
		} else { /* 非圧縮 */
			while (1) {
				/* read header */
				if (fread(head,6,1,fp)==0) return(1);
				if ((wx=ctos80(head))==0) break; /* end of data */
				/* read line data */
				if (fread(line,(wx+7)/8*(mode==1? 16:4),1,fp)==0) return(1);
				y=ctos80(&head[4]);
				if (y<512) func(ctos80(&head[2]),y,line,wx);
			}
		}
	}
	return(0);
}

/*****************************************************************************/
