/*
 *						'Magl.exp' 		for FM-TOWNS
 *
 *				- MAKIchan Graphic loader is not 鮪だ！ -
 *
 *					Version 0.41	Update 1991/05/03
 *
 *							programmed by MALOR
 */

/*
 *			1991/03/08	v0.01	正常に展開されたぞ
 *					10	v0.02	アセンブラ化して高速化！９８にやっと勝てた…
 *								さらに、文字列操作命令を導入してみた。
 *					13	v0.03	ビット操作命令の導入を考えるが､サイクル数が
 *								違わないので､やっぱりやめた(T_T)
 *								256色/DOS互換モード対応･アセンブラ化
 *								オフセットロード対応
 *								画面はみ出しチェック強化(う〜ん、手抜きじゃ)
 *					18	v0.04	MKI対応のため､仕様変更
 *					22	v0.05	ループ展開で、改良？改悪？
 *					25	v0.06	98版で採用されている１パス方式を試してみるが、
 *								今のバージョンに勝てなかった....
 *								だから、実は何も変わっていない。徒労だ....
 *					29	v0.10	MKIフォーマットにも対応
 *					30	v0.11	正式公開版仕様書を見てビックリ！
 *								随分変わっているんですね。で、手直しバージョン
 *								おまけで、ワイルドカード対応
 *				 04/02	v0.20	ライブラリ化で大改造
 *								メモリに展開するようにして、大画面対応
 *								表示後の拡大縮小・スクロールに対応
 *					09	v0.30	展開時のエフェクト機能装備
 *					17	v0.31	yamato.magが表示できないバグ修正
 *								データの誤認バグ修正
 *								TOWNS-OS上でキー入力ができないバグ修正
 *								エフェクト時に480ライン目が表示されないバク修正
 *					27	v0.35	｢256色まぐでーた｣に本当に対応 :-)
 *								差分まぐろが表示できないバグ修正
 *								画像の左上でスクロールを止まるようにした。
 *				 05/03	v0.40	フラグデータによる特化で高速化!
 *						v0.41	少しオプションを追加・変更
 *								差分まぐろがエフェクト表示できないバグ修正
 *  今後の課題
 *		ファイラーを付ける
 *		セーバーを作ろう(^-^;)
 *		ハイパフォーマンスセーバーはできるのだろうか…
 */

#include <egb.h>
#include <mos.h>
#include <msdos.cf>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "wild.h"
#include "mag.h"
#include "pixel.h"

#define VERSION	"0.41"
#define UPDATE	"1991/05/03 17:35"

#define tolower(x) (((x)<='Z')&&((x)>='A')?((x)-'A'+'a'):(x))

#define Key_UP		0x1e
#define Key_DOWN	0x1f
#define Key_RIGHT	0x1c
#define Key_LEFT	0x1d
#define ESC			0x0b

#define PAD_UP		0x3e
#define PAD_DOWN	0x3d
#define PAD_RIGHT	0x37
#define PAD_LEFT	0x3b
#define PAD_BTN_A	0x2f
#define PAD_BTN_B	0x1f
#define PAD_RUN		0x33
#define PAD_SELECT	0x3c

#define MOS_BTN_LEFT	1
#define MOS_BTN_RIGHT	2

#define Effect_NUM		5
#define Effect_Falcom	1
#define Effect_Slide	2
#define Effect_Sima1	3
#define Effect_Sima2	4
#define Effect_Mosaic	5
#define Effect_Nijimi	6

#define CLS				0x01
#define WAIT			0x02
#define INFO			0x04
#define LIST			0x08
#define DEBUG			0x10
#define SEARCH_STR		0x20
#define SEARCH_FNAME	0x40

/* Prototype declaration */

int		effect_display(int effect,int dx,int dy);
int		set_screen(int mode);
int		key_scroll(int (*roll)(int arg,int dx,int dy),int dx,int dy);
int		matta(void);
void	init_scroll(void);
int		scroll(int arg,int dx,int dy);
int		scroll_mem(int arg,int dx,int dy);
int		scroll_nijimi(int arg,int dx,int dy);
int		crtc(int addr,int dat);
int		get_second(void);
int		find(char *s,char *d);

void falcom(int xbyte,int sy,int sofs,int slofs,int dseg,int dofs,int dlofs);
	/* ファルコム効果      注意:dest.offsetは展開領域左下のアドレスを渡す */
void slide(int xbyte,int sy,int sofs,int slofs,int dseg,int dofs,int dlofs);
void sima2(int xbyte,int sy,int sofs,int slofs,int dseg,int dofs,int dlofs,int step);
void mosaic(int xbyte,int sy,int sofs,int slofs,int dseg,int dofs,int dlofs,int dx,int dy,int midofs);
void mosaic256(int xbyte,int sy,int sofs,int slofs,int dseg,int dofs,int dlofs,int dx,int dy,int midofs);
void nijimi(int xbyte,int sy,int sofs,int slofs,int dseg,int dofs,int dlofs);
int  setpal(int count,int wight,int nwight,char *beforepal,char *afterpal,int start);
void cls(int xbyte,int sy,int dseg,int dofs,int dlofs);
	/* These functions exist in 'effect.asm' */

/* Global Vari. */

char	egbwork[EgbWorkSize];		/* EGBライブラリ用ワーク */
char	moswork[MosWorkSize];		/* MOUSEライブラリ用ワーク */
char	apal[768],bpal[768];		/* ｢ぢわっ｣と表示用パレット */
static int ny=0;					/* スクロール用ワーク */
static int vx=0,vy=0,rate=0;

/* Main program */

int		effect_display(int effect,int dx,int dy)
{
	static int count=0;
	int ssx,sx,sx2,sy,sy2,y,yy,i;

	sx = ((rx-lx+1)>640)?640:(rx-lx+1);		/* エフェクト時の横幅 */
	sx2 = rx-lx+1;							/* 全画面表示時の横幅 */
	ssx = (rx/8-lx/8+1)*8;					/* 8ドット拡張後の横幅 */
	sy = ((ry-ly>479)?480:(ry-ly+1));
	sy2 = ((ry-ly>511)?512:(ry-ly+1));

	if (!(screen_mode&COL256)) {
		sx2 = sx2+sx2%2;
		sx = sx+sx%2;
	}

	if (effect==-1)
		effect = (rand()*Effect_NUM)/RAND_MAX + 1 ;

	switch(effect) {
		case Effect_Falcom :
			if (screen_mode&COL256)
				falcom(sx,sy,(int)vram+lx%4,ssx,0x010c,(dx+(dy+sy-1)*1024),1024);
			else
				falcom(sx/2,sy,(int)vram+(lx%8)/2,ssx/2,0x0104,(dx+(dy+sy-1)*1024)/2,512);
			display(0,0,sx2,sy2,dx,dy);
			break;
		case Effect_Slide :
			if (screen_mode&COL256)
				slide(sx,sy,(int)vram+lx%4,ssx,0x010c,(dx+dy*1024),1024);
			else
				slide(sx/2,sy,(int)vram+(lx%8)/2,ssx/2,0x0104,(dx+dy*1024)/2,512);
			display(0,0,sx2,sy2,dx,dy);
			break;
		case Effect_Sima1 :
			for (yy=0;yy<20;yy++)
				for(y=yy;y<sy;(y+=20)) {
					display(0,y,sx,1,dx,dy+y);
					for(i=0;i<300;i++);
				}
			display(0,0,sx2,sy2,dx,dy);
			break;
		case Effect_Sima2 :
			i=23;
			while(((sx*sy)%i)==0) i++;
			if (screen_mode&COL256)
				sima2(sx,sy,(int)vram+lx%4,ssx,0x010c,(dx+dy*1024),1024,i);
			else
				sima2(sx/2,sy,(int)vram+(lx%8)/2,ssx/2,0x0104,(dx+dy*1024)/2,512,i);
			display(0,0,sx2,sy2,dx,dy);
			break;
		case Effect_Mosaic :
			if (screen_mode&COL256)
				for(i=64;i>0;i-=4)
					mosaic256(sx,sy,(int)vram+lx%4,ssx,0x010c,(dx+dy*1024),1024,i,i,i/2+(i/2)*ssx);
			else
				for(i=64;i>0;i-=4)
					mosaic(sx/2,sy,(int)vram+(lx%8)/2,ssx/2,0x0104,(dx+dy*1024)/2,512,i/2,i,i/4+((i/2)*ssx)/2);
			display(0,0,sx2,sy2,dx,dy);
			break;
		case Effect_Nijimi :
			screen_mode |= COL256;
			if (count==0||(image_mode&COL256)) {
				cls(1024,512,0x010c,0,1024);
				set_screen(screen_mode);			/* 最初は真っ暗 */
				for(i=0;i<768;i++)
					bpal[i]=0;
				for(;setpal(51,0,0,bpal,bpal,0)==0;);
				for(;setpal(51,0,0,bpal+ 51*3,bpal+ 51*3,51 )==0;);
				for(;setpal(51,0,0,bpal+102*3,bpal+102*3,102)==0;);
				for(;setpal(51,0,0,bpal+153*3,bpal+153*3,153)==0;);
				for(;setpal(52,0,0,bpal+204*3,bpal+204*3,204)==0;);
			}
			if (image_mode&COL256) {
				count = -1;
				cls(1024,512,0x010c,0,1024);
				display(0,0,sx2,sy2,dx,dy);
				for(i=0;i<256;i++) {
					apal[i*3  ] = pal[i*3+2];
					apal[i*3+1] = pal[i*3+1];
					apal[i*3+2] = pal[i*3  ];
				}
			} else {
				outpb(0x458,0);
				outpb(0x45a,((count%2==0)?0x0f:0xf0));
				outpb(0x45b,((count%2==0)?0x0f:0xf0));
				outpb(0x458,1);
				outpb(0x45a,((count%2==0)?0x0f:0xf0));
				outpb(0x45b,((count%2==0)?0x0f:0xf0));
				cls(1024,512,0x010c,0,1024);
				nijimi(sx2/2,sy2,(int)vram+(lx%8)/2,ssx/2,0x010c,dx+dy*1024,1024);
				outpb(0x458,0);
				outpb(0x45a,0xff);
				outpb(0x45b,0xff);
				outpb(0x458,1);
				outpb(0x45a,0xff);
				outpb(0x45b,0xff);
				if(count%2==0)
					for(i=0;i<256;i++) {
						apal[i*3  ] = pal[(i&0xf)*3+2];
						apal[i*3+1] = pal[(i&0xf)*3+1];
						apal[i*3+2] = pal[(i&0xf)*3  ];
					}
				else
					for(i=0;i<256;i++) {
						apal[i*3  ] = pal[(i>>4)*3+2];
						apal[i*3+1] = pal[(i>>4)*3+1];
						apal[i*3+2] = pal[(i>>4)*3  ];
					}
			}
			for(i=0;i<65;i++) {
				for(;setpal(51,i,64-i,apal,bpal,0)==0;);
				for(;setpal(51,i,64-i,apal+ 51*3,bpal+ 51*3,51 )==0;);
				for(;setpal(51,i,64-i,apal+102*3,bpal+102*3,102)==0;);
				for(;setpal(51,i,64-i,apal+153*3,bpal+153*3,153)==0;);
				for(;setpal(52,i,64-i,apal+204*3,bpal+204*3,204)==0;);
			}
			for(i=0;i<768;i++)
				bpal[i]=apal[i];
			count++;
			break;
		default :
			display(0,0,sx2,sy2,dx,dy);
			break;
	}

	return TRUE;

}

void init_scroll(void)
{
	int yrate;

	ny = 0; vy = 0; vx = 0; rate = 0;

	if (screen_mode&LINE200)
		yrate = rate+1;
	else
		yrate = rate;
	if (screen_mode&COL256) {
		crtc(17,(vx+vy*1024)/8);
		crtc(21,(vx+vy*1024)/8);
		crtc(27,(yrate<<12)|(rate<<8)|(yrate<<4)|rate);
	} else {
		crtc(17,(vx+vy*1024)/8);
		crtc(27,(yrate<<4)|(rate));
	}

}

int scroll(int arg,int dx,int dy)
{
	int yrate;

	switch(arg) {
		case Scroll_UP :
			vy--;
			if (vy==-1) vy = 0;
			break;
		case Scroll_DOWN :
			vy++;
			if (vy==512) vy = 0;
			break;
		case Scroll_RIGHT :
			vx++;
			if (vx==1024) vx = 0;
			break;
		case Scroll_LEFT :
			vx--;
			if (vx==-1) vx = 0;
			break;
		case Zoom_UP :
			rate++;
			if (screen_mode&LINE200) {
				if (rate==15)
					rate = 14;
				}
			else {
				if (rate==16)
					rate = 15;
			}
			break;
		case Zoom_DOWN :
			rate--;
			if (rate==-1)
				rate = 0;
			break;
		default :
			return FALSE;
	}
	if (screen_mode&LINE200)
		yrate = rate+1;
	else
		yrate = rate;
	if (screen_mode&COL256) {
		crtc(17,(vx+vy*1024)/8);
		crtc(21,(vx+vy*1024)/8);
		crtc(27,(yrate<<12)|(rate<<8)|(yrate<<4)|rate);
	} else {
		crtc(17,(vx+vy*1024)/8);
		crtc(27,(yrate<<4)|(rate));
	}
	return TRUE;
}


int scroll_mem(int arg,int dx,int dy)
{
	int yrate;

	switch(arg) {
		case Scroll_UP :
			ny--;
			if (ny==-1) {
				ny = 0;
				break;
				/* ny = ry - ly; */
			}
			display(lx,ny,rx-lx+1,1,dx,((vy-1)<0)?511:(vy-1));
			vy--;
			if (vy==-1) vy = 511;
			break;
		case Scroll_DOWN :
			ny++;
			if (ny==(ry-ly+1))
				ny = 0;
			display(lx,((511+ny)>(ry-ly))?(511+ny+ly-ry-1):511+ny
				,rx-lx+1,1,dx,((vy-1)<0)?511:(vy-1));
			vy++;
			if (vy==512) vy = 0;
			break;
		case Scroll_RIGHT :
			vx++;
			if (vx==1024) vx = 0;
			break;
		case Scroll_LEFT :
			vx--;
			if (vx==-1) vx = 0;
			break;
		case Zoom_UP :
			rate++;
			if (screen_mode&LINE200) {
				if (rate==15)
					rate = 14;
				}
			else {
				if (rate==16)
					rate = 15;
			}
			break;
		case Zoom_DOWN :
			rate--;
			if (rate==-1)
				rate = 0;
			break;
		default :
			return FALSE;
	}
	if (screen_mode&LINE200)
		yrate = rate+1;
	else
		yrate = rate;
	if (screen_mode&COL256) {
		crtc(17,(vx+vy*1024)/8);
		crtc(21,(vx+vy*1024)/8);
		crtc(27,(yrate<<12)|(rate<<8)|(yrate<<4)|rate);
	} else {
		crtc(17,(vx+vy*1024)/8);
		crtc(27,(yrate<<4)|(rate));
	}
	return TRUE;

}

int scroll_nijimi(int arg,int dx,int dy)
{
	int yrate;

	switch(arg) {
		case Scroll_UP :
			ny--;
			if (ny==-1) {
				ny = 0;
				break;
				/* ny = ry - ly; */
			}
			nijimi((rx-lx+1)/2,1,(int)vram+(lx%8+lx+ny*(rx-lx+1))/2
				,(rx-lx+1)/2,0x10c,dx+(((vy-1)<0)?511:(vy-1))*1024,1024);
			vy--;
			if (vy==-1) vy = 511;
			break;
		case Scroll_DOWN :
			ny++;
			if (ny==(ry-ly+1))
				ny = 0;
			nijimi((rx-lx+1)/2,1,
				(int)vram+(lx%8+lx+(((511+ny)>(ry-ly))?(511+ny+ly-ry-1):511+ny)
															*(rx-lx+1))/2,
				(rx-lx+1)/2,0x10c,dx+(((vy-1)<0)?511:(vy-1))*1024,1024);
			vy++;
			if (vy==512) vy = 0;
			break;
		case Scroll_RIGHT :
			vx++;
			if (vx==1024) vx = 0;
			break;
		case Scroll_LEFT :
			vx--;
			if (vx==-1) vx = 0;
			break;
		case Zoom_UP :
			rate++;
			if (screen_mode&LINE200) {
				if (rate==15)
					rate = 14;
				}
			else {
				if (rate==16)
					rate = 15;
			}
			break;
		case Zoom_DOWN :
			rate--;
			if (rate==-1)
				rate = 0;
			break;
		default :
			return FALSE;
	}
	if (screen_mode&LINE200)
		yrate = rate+1;
	else
		yrate = rate;
	crtc(17,(vx+vy*1024)/8);
	crtc(21,(vx+vy*1024)/8);
	crtc(27,(yrate<<12)|(rate<<8)|(yrate<<4)|rate);
	return TRUE;

}

int			crtc(int addr,int dat)
{
	outpb(0x440,addr);
	outpb(0x443,dat>>8);
	outpb(0x442,dat&0xff);
	return TRUE;
}

int		set_screen(int mode)
{
	static	int	preplane=0;

	if ((mode&(COL256|LINE200))==(preplane&(COL256|LINE200))) return TRUE;

	preplane = mode;

	if (mode&DOS) return TRUE;

	if (mode&COL256) {					/* 256色モード */
		EGB_resolution(egbwork,0,12);
		EGB_writePage(egbwork,0);
		EGB_displayPage(egbwork,0,1);	/* レイア０に書き込む */
	} else {							/* 16色モード */
		EGB_resolution(egbwork,0,3);
		EGB_resolution(egbwork,1,3);
		EGB_writePage(egbwork,0);
		EGB_displayPage(egbwork,1,1);	/* レイア０に書き込む */
	}
	
	if (mode&LINE200)					/* 縦横比2:1に設定 */
		crtc(27,(1<<12)|(0<<8)|(1<<4)|0);
		/* EGB_displayStart(egbwork,2,1,2); */

	return TRUE;
}

int		matta(void)
{
	Registers.AX.R = 0x0C00;			/* キーバッファの初期化 */
	calldos();

	for(;;) {
		Registers.AX.R = 0x0600;		/* 直接コンソール入力 */
		Registers.DX.R = 0x00FF;
		calldos();
		if (tolower(Registers.AX.LH.L)==(int)'q'||
				tolower(Registers.AX.LH.L)=='e'||
					Registers.AX.LH.L==ESC)
			return FALSE;
		if (Registers.AX.LH.L!=0)
			break;
		if((inpb(0x04d0)&0x30)!=0x30)		/* パッド・マウスチェック */
			break;
		if((inpb(0x04d2)&0x30)!=0x30)
			break;
	}

	return TRUE;

}

int		key_scroll(int (*roll)(int arg,int dx,int dy),int dx,int dy)
{
	int flag,now,x,y,btn,dummy;

	MOS_motion(&x,&y);
	x = 0;
	y = 0;

	flag = TRUE;
	for(;flag;) {
		Registers.AX.R = 0x0600;		/* 直接コンソール入力 */
		Registers.DX.R = 0x00FF;
		calldos();
		switch(tolower(Registers.AX.LH.L)) {
			case Key_UP :
				(*roll)(Scroll_UP,dx,dy);
				break;
			case Key_DOWN :
				(*roll)(Scroll_DOWN,dx,dy);
				break;
			case Key_RIGHT :
				(*roll)(Scroll_RIGHT,dx,dy);
				break;
			case Key_LEFT :
				(*roll)(Scroll_LEFT,dx,dy);
				break;
			case 'e' :
			case 'q' :
				return FALSE;
			case 'n' :
				flag = FALSE;
				break;
			case 'z' :
			case CR :
				(*roll)(Zoom_UP,dx,dy);
				break;
			case 'd' :
			case ' ' :
				(*roll)(Zoom_DOWN,dx,dy);
				break;
		}
		switch((now=inpb(0x4d0)&0x3f)) {
			case PAD_UP :
				(*roll)(Scroll_UP,dx,dy);
				break;
			case PAD_DOWN :
				(*roll)(Scroll_DOWN,dx,dy);
				break;
			case PAD_RIGHT :
				(*roll)(Scroll_RIGHT,dx,dy);
				break;
			case PAD_LEFT :
				(*roll)(Scroll_LEFT,dx,dy);
				break;
			case PAD_RUN :
			case PAD_SELECT :
				flag = FALSE;
				break;
			case PAD_BTN_A :
				(*roll)(Zoom_UP,dx,dy);
				for(;now==(inpb(0x4d0)&0x3f););
				break;
			case PAD_BTN_B :
				(*roll)(Zoom_DOWN,dx,dy);
				for(;now==(inpb(0x4d0)&0x3f););
				break;
		}
		MOS_motion(&x,&y);
		if (x>0)
			for(;x!=0;x--) (*roll)(Scroll_RIGHT,dx,dy);
		else
			for(;x!=0;x++) (*roll)(Scroll_LEFT,dx,dy);
		if (y>0)
			for(;y!=0;y--) (*roll)(Scroll_DOWN,dx,dy);
		else
			for(;y!=0;y++) (*roll)(Scroll_UP,dx,dy);
		MOS_rdpos(&now,&dummy,&dummy);
		btn = now;
		if (now==MOS_BTN_LEFT) {
			for(;now==btn;) MOS_rdpos(&now,&dummy,&dummy);
			(*roll)(Zoom_UP,dx,dy);
		}
		if (now==MOS_BTN_RIGHT) {
			for(;now==btn;) MOS_rdpos(&now,&dummy,&dummy);
			(*roll)(Zoom_DOWN,dx,dy);
		}
		if (now==(MOS_BTN_LEFT|MOS_BTN_RIGHT))
			flag = FALSE;
	}

	return TRUE;

}

int		get_second(void)
{
	Registers.AX.LH.H = 0x2c;				/* 時間取得ファンクションコール */

	calldos();

	return Registers.DX.LH.H;
}

int		find(char *s,char *d)
{
	for(;*s!='\0';s++)
		if ((tolower(*s))==(tolower(*d)))
			if (stringcmp(d,s))
				return TRUE;

	return FALSE;
}

void	main(int argc,char *argv[])
{
	int n,i,mode=0,view_mode=WAIT,dx=-1,dy=0,dc;
	int ddx,ddy,effect=0,ret=TRUE;
	char *p,path[BufSize],fname[BufSize];
	char search_fname[BufSize],search_str[BufSize];
	FILE *fp;
	DTA *dta;

	mode = 0;
	view_mode = WAIT;
	dx = -1;
	dy = 0;
	effect = 0;
	ret = TRUE;

	/*
	EGB_init(egbwork,EgbWorkSize);
	fp=fopen("g:\\mag\\yamato.mag","rb");
	mag_get_head(fp);
	set_palette(fp);
	printf("magl : mag decode start\n");
	mag_decode(fp,0,0,0);
	key_scroll(scroll_mem,0,0);
	exit(0);
	*/

	if (argc==1) {
		printf("MAGloader 'magl.exp'    Version "VERSION"\n\n"
			   " [Usage ] : run386 magl [{/|-}<Option>] <filename> ･･･ \n"
			   " [Option] : -lm          load as ms-dos screen mode\n"
			   "            -lv          load to vram\n"
			   "            -d           comment list\n"
			   "            -i           information list\n"
			   "            -f <fname>   display data which follow this file\n"
			   "            -u <string>  display data which is including this string\n"
			   "            -o [<x> <y>] display Offset\n"
			   "            -k[+/-]      key wait flag (default=on)\n"
			   "            -c[+/-]      clear screen flag (default=off)\n"
			   "            -e [<num>]   special effect\n"
			   "            -#           display revision\n");
		exit(0);
	}

	for(n=1;n<argc;)								/* option process */
		if (argv[n][0]=='-'||argv[n][0]=='/') {
			switch(tolower(argv[n][1])) {
				case 'l' :
					if (tolower(argv[n][2])=='m')
						mode |= DOS;
					else if (tolower(argv[n][2])=='v')
						mode |= VRAM;
					dc = 1;
					break;
				case 'o' :
					if (argv[n+1][0]>'0'&&argv[n+1][0]<'9') {
						dx = atoi(argv[n+1]);
						dy = atoi(argv[n+2]);
						dc = 3;
					} else {
						dx = 0;
						dy = 0;
						dc = 1;
					}
					break;
				case 'k' :
					switch(argv[n][2]) {
						case '+' :
							view_mode |= WAIT;
							break;
						case '-' :
							view_mode &= (~WAIT);
							break;
						default :
							view_mode ^= WAIT;
							break;
					}
					dc = 1;
					break;
				case 'c' :
					switch(argv[n][2]) {
						case '+' :
							view_mode |= CLS;
							break;
						case '-' :
							view_mode &= (~CLS);
							break;
						default :
							view_mode ^= CLS;
							break;
					}
					dc = 1;
					break;
				case '@' :
					view_mode |= DEBUG;
				case 'i' :
					view_mode |= INFO;
					dc = 1;
					break;
				case 'd' :
					view_mode |= LIST;
					mode |= DOS;
					dc = 1;
					break;
				case 'u' :
					view_mode |= SEARCH_STR;
					strcpy(search_str,argv[n+1]);
					dc = 2;
					break;
				case 'f' :
					view_mode |= SEARCH_FNAME;
					strcpy(search_fname,argv[n+1]);
					dc = 2;
					break;
				case 'e' :
					if (argv[n][2]!='\0') {
						effect = atoi(argv[n]+2);
						dc = 1;
						break;
					}
					if (argv[n+1][0]>'0'&&argv[n+1][0]<'9') {
						effect = atoi(argv[n+1]);
						dc = 2;
					} else {
						effect = -1;
						dc = 1;
					}
					break;
				case '#' :
					printf(
						"          'magl.exp' for FM-Towns\n"
						" - MAKIchan Graphic loader is not 鮪だ！ - \n"
						"\n"
						"  Version "VERSION"    update "UPDATE"\n"
						);
					exit(0);
					break;
				default :
					printf("\nunidentified option : %s\n",argv[n]);
					dc = 1;
					break;
				}
			for(i=n;i<argc-dc;i++)
				argv[i] = argv[i+dc];
			argc -= dc;
		} else
			n++;

	/* 「ぢわっ」と表示は非DOSモードのみ */
	if (effect==Effect_Nijimi) {
		mode = mode&(~DOS);
	}

	srand((unsigned int)get_second());
	if (!(mode&DOS)) {
		EGB_init(egbwork,EgbWorkSize);
		EGB_writePage(egbwork,0);
		EGB_displayPage(egbwork,1,1);	/* レイア０に書き込む */
		MOS_start(moswork,MosWorkSize);
		MOS_disp(0);
	}

	printf(
"filename mode   saved user               memo\n"
"======== ======= ==== ================== =======================================");

	for (n=1;n<argc;n++) {
		*path = '\0';
		for (;;) {
			if (*path=='\0') {
				strcpy(path,argv[n]);
				if (getext(path)==NULL) {
					strcat(path,".*");
				}
				dta=search(path,0,fname);
			} else
				dta=next(path,0,fname);
			if (*fname=='\0')
				break;

			if (view_mode&SEARCH_FNAME)
				if (stringcmp(search_fname,getname(fname)))
					view_mode &= (~SEARCH_FNAME);
				else
					continue;

			fp = (FILE *)NULL;
			if ((fp=fopen(fname,"rb"))==NULL) {
				printf("magl : can't open file\n");
				continue;
			}

			if (mag_get_head(fp)) {
				if (view_mode&SEARCH_STR)
					if (!find(comment+8,search_str)) {
						fclose(fp);
						continue;
					}
				for (p=getname(fname),i=0;i<8;i++)
					putchar(((*p=='.')?' ':*p++));		/* ファイル名出力 */
				putchar(' ');
				for (p=comment,i=0;i<70;i++)			/* コメント出力 */
					putchar(((*p=='\0')?' ':*p++));
				putchar(0x0d);
				putchar(0x0a);
				if (view_mode&INFO)
					printf(
"                                         [rate]:%6d/%6d (%3d%%)\n"
"                                         [saved rectangle]:(%3d,%3d)-(%3d,%3d)\n"
"                                         [machine]:$%2x [flag]:$%2x [screen]:$%2x\n"
					,dta->size,siza*32,(dta->size)*100/siza/32
					,lx,ly,rx,ry,maghead.machine,maghead.rflg,maghead.screen);
				if (view_mode&DEBUG)
					printf( "+------+OFFSET-+--SIZE-+\n"
							"|flag a| %5d | %5d |\n"
							"|flag b| %5d | %5d |\n"
							"|pixel | %5d | %5d |\n"
							"+------+-------+-------+\n"
					,maghead.offa,siza,maghead.offb
					,maghead.sizb,maghead.offp,maghead.sizp);
				if (view_mode&LIST) {					/* リスティング */
					fclose(fp);
					continue;
				}
				screen_mode |= mode;
				if(mode&VRAM) {
					if (view_mode&CLS)
						cls(1024,512,0x010c,0,1024);
					set_screen(screen_mode);
					set_palette();
				}
				/* printf("magl : start mag_decode \n"); */
				mag_decode(fp,mode,dx,dy);
			} else if (mki_get_head(fp)) {
				if (view_mode&SEARCH_STR)
					if (!find(mkihead.comment,search_str)) {
						fclose(fp);
						continue;
					}
				for (p=getname(fname),i=0;i<8;i++)
					putchar(((*p=='.')?' ':*p++));
				printf(" %s",mkihead.id);
				putchar(0x0d);
				putchar(0x0a);
				if (view_mode&INFO)
					printf(
"                                         [rate]:%6d/%6d (%3d%%)\n"
"                                         [saved rectangle]:(  0,  0)-(639,399)\n"
					,dta->size,12800,(dta->size)/128);
				if (view_mode&DEBUG)
					printf( "+------+--SIZE-+------+--SIZE-+\n"
							"|flag a| %5d |flag b| %5d |\n"
							"|pixela| %5d |pixelb| %5d |\n"
							"+------+-------+------+--SIZE-+\n"
					,maghead.offa,siza,maghead.offb
					,maghead.sizb,maghead.offp,maghead.sizp);
				if (view_mode&LIST) {
					fclose(fp);
					continue;
				}
				screen_mode |= mode;
				if(mode&VRAM) {
					if (view_mode&CLS)
						cls(1024,512,0x010c,0,1024);
					set_screen(screen_mode);
					set_palette();
				}
				mki_decode(fp,mode,dx,dy);
			} else {
				fclose(fp);
				continue;
			}

			if (dx==-1) {				/* VRAM表示位置調整 */
				ddx = lx;
				ddy = ly;
			} else {
				ddx = dx;
				ddy = dy;
			}

			if (mode&DOS) {			/* x方向にはみ出す時は抑止 */
				if (ddx+rx-lx+1>640)
					ddx = 0;
			} else {
				if (ddx+rx-lx+1>1024)
					ddx = 0;
			}

			fclose(fp);

			if ((!(mode&VRAM))&&(effect!=Effect_Nijimi)) {
				if (view_mode&CLS)
					cls(1024,512,0x010c,0,1024);
				set_screen(screen_mode);
				set_palette();
			}
			
			if (view_mode&WAIT)				/* 展開後処理 */
				if (vram==NULL)
					if (mode&DOS)
						ret=matta();
					else {
						init_scroll();
						ret=key_scroll(scroll,0,0);
						init_scroll();
					}
				else {
					if ((!(mode&DOS))&&(effect!=0))
						effect_display(effect,ddx,ddy);
					else
						display(0,0,rx-lx+1,((ry-ly>511)?512:(ry-ly+1)),ddx,ddy);
					if ((effect==Effect_Nijimi)&&(!(image_mode&COL256))) {
						init_scroll();
						if (ry-ly+1>512)
							ret=key_scroll(scroll_nijimi,ddx,ddy);
						else
							ret=key_scroll(scroll,0,0);
						init_scroll();
					} else if (mode&DOS)
						ret=matta();
					else {
						init_scroll();
						if (ry-ly+1>512)
							ret=key_scroll(scroll_mem,ddx,ddy);
						else
							ret=key_scroll(scroll,0,0);
						init_scroll();
					}
				}
			else
				if (vram!=NULL)
					if ((!(mode&DOS))&&effect!=0)
						effect_display(effect,ddx,ddy);
					else
						display(0,0,rx-lx+1,((ry-ly>511)?512:(ry-ly+1)),ddx,ddy);
			if (vram!=NULL)				/* イメージ格納域開放 */
				free(vram);

			if (ret==FALSE)				/* 中断して脱出 */
				goto Exit;

		}
	}

Exit:
	if (!(mode&DOS))
		MOS_end();

}
