#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winb.h>
#include <te.h>
#include <fntb.h>
#include <gui.h>
#include <file_dlg.h>
#include <tifflib.h>
#include <egb.h>
#include <mos.h>
#include <snd.h>
#include "video.h"
#include "ugoku.h"
#include "old_mov.h"
#include "mrcdef.h"

#define VRAMOFST 262144		/* VRAM OFFSET FOR FRAME ORIGINAL DATA */

extern	int		mouseSwCheck() ;
extern	int		errorCheck( int ) ;

extern	char	*guiEgbPtr ;	/*	EGB のワークアドレス	*/
extern	char	*rbuf ;			/*	自家製のワークアドレス	*/
extern	char	*bbuf ;			/*	自家製のワークアドレス	*/
extern	int	xtif, ytif ;		/*	tiffdataの縦横幅	*/
//extern char tifName[][16] ;
//extern int tifTotal ;

extern int	baseDialogId ;

int	pacDialogId = -1 ;
int	pacSubDialogId = -1 ;
int	pacRoughBar = -1 ;
int	pacRoughNumId = -1 ;
int	pacMesId[8] = -1 ;
int	pacTIconId[2] = -1 ;
int	pacFilterBar = -1 ;
int	pacFilterNumId = -1 ;
int	pacOKBtnId = -1 ;
int	pacCanBtnId = -1 ;
int	pacWaitDialogId = -1 ;
int	pacWaitMesId[2] = -1 ;
int	pacWaitNumId[2] = -1 ;

static int svar[] = { 0,0,0,0,0,0,319,239,0,0,0, 0,0,0 };
/*
	svar[] = { frame, total_byte, rough, premove, x0,y0,x1,y1, b,r,g,
		   soft, color_rate, mode }
					       ↑ ↑この2つは外部からいじってはだめ
*/
static int pacRough = 0 ;
static int idouMode = 1 ;
static int pacFilter = 0 ;
static int pacOkFlg ;

/* 動画作成(新規) */
tifToMov( namemov, path, total, nbuffer )
char *namemov, path[], nbuffer[][16] ;
int total ;
{
	int error ;

	MMI_SendMessage( pacDialogId, MM_ATTACH, 1, baseDialogId ) ;
	MTL_setFlagObj( pacTIconId[idouMode+0], (MS_UNSELECT | MS_TOGGLE) ) ;

	MMI_SendMessage( pacDialogId, MM_SHOW, 0 ) ; /* 見せる */

	MMI_ExecSystem() ;		/* Dialog表示へ･･･イベントループ */
	svar[0] = 0 ;
	svar[1] = 0 ;
	svar[2] = pacRough ;
	svar[3] = idouMode * 8 ;
	svar[11] = pacFilter ;

	MMI_SendMessage( pacDialogId, MM_ERASE, 0 ) ;
	MMI_SendMessage( pacDialogId, MM_DETACH, 0 ) ;

	error = 0 ;
	if( pacOkFlg == TRUE )
	{
		EGB_writePage(guiEgbPtr,1);
		EGB_color( guiEgbPtr, 1, 0 ) ;
		EGB_clearScreen(guiEgbPtr);			/* clear */
		EGB_displayStart(guiEgbPtr,3,0,0);
		EGB_displayStart(guiEgbPtr,2,1,1);
		EGB_displayStart(guiEgbPtr,2,2,2);
		EGB_displayStart(guiEgbPtr,0,0,0);
		EGB_displayStart(guiEgbPtr,1,0,0);
		EGB_displayStart(guiEgbPtr,3,320,240);
		EGB_displayPage(guiEgbPtr,0,3);
		EGB_writePage(guiEgbPtr,0);			/* pageを元に戻さないと暴走 */

		tifToMovSet( total ) ;

		SetMouse16( 81, 0xf, 0x8 ) ;	/* マウスカーソルをウエイト表示 */
		error = mov_save( namemov, path, total, nbuffer ) ;
		SetMouse16( 80, 0xf, 0x8 ) ;	/* マウスカーソルを元に */

		tifToMovReset() ;

		EGB_displayPage(guiEgbPtr,0,1);
	}

	MMI_FlushEvnt() ;	/* イベントをフラッシュ */
	/* マウスが押されていれば次のイベントを無視 */
	if( mouseSwCheck() )TL_setInvalidMosFlag() ;

	if( error )
	{
		errorCheck( error ) ;
	}

	return NOERR ;
}

/* 動画作成(追加) */
tifToMovAdd( namemov, path, total, nbuffer )
char *namemov, path[], nbuffer[][16] ;
int total ;
{
	int error ;

	MMI_SendMessage( pacDialogId, MM_ATTACH, 1, baseDialogId ) ;
	MTL_setFlagObj( pacTIconId[idouMode+0], (MS_UNSELECT | MS_TOGGLE) ) ;

	MMI_SendMessage( pacDialogId, MM_SHOW, 0 ) ; /* 見せる */

	MMI_ExecSystem() ;		/* Dialog表示へ･･･イベントループ */

	svar[2] = pacRough ;
	svar[3] = idouMode * 8 ;
	svar[11] = pacFilter ;

	MMI_SendMessage( pacDialogId, MM_ERASE, 0 ) ;
	MMI_SendMessage( pacDialogId, MM_DETACH, 0 ) ;

	error = 0 ;
	if( pacOkFlg == TRUE )
	{
		EGB_writePage(guiEgbPtr,1);
		EGB_color( guiEgbPtr, 1, 0 ) ;
		EGB_clearScreen(guiEgbPtr);			/* clear */
		EGB_displayStart(guiEgbPtr,3,0,0);
		EGB_displayStart(guiEgbPtr,2,1,1);
		EGB_displayStart(guiEgbPtr,2,2,2);
		EGB_displayStart(guiEgbPtr,0,0,0);
		EGB_displayStart(guiEgbPtr,1,0,0);
		EGB_displayStart(guiEgbPtr,3,320,240);
//		EGB_displayPage(guiEgbPtr,0,2);
		EGB_displayPage(guiEgbPtr,0,0);
		EGB_writePage(guiEgbPtr,0);			/* pageを元に戻さないと暴走 */

		error = mov_head_read(namemov, svar) ;	/* head読んでframeを送る */
		if( error == NOERR )
		{
			tifToMovSet( total ) ;
			EGB_displayPage(guiEgbPtr,0,3);

			SetMouse16( 81, 0xf, 0x8 ) ;	/* マウスカーソルをウエイト表示 */
			error = mov_save( namemov, path, total, nbuffer ) ;
			SetMouse16( 80, 0xf, 0x8 ) ;	/* マウスカーソルを元に */

			tifToMovReset() ;
		}
		EGB_displayPage(guiEgbPtr,0,1);
	}

	MMI_FlushEvnt() ;	/* イベントをフラッシュ */
	/* マウスが押されていれば次のイベントを無視 */
	if( mouseSwCheck() )TL_setInvalidMosFlag() ;

	if( error )
	{
		errorCheck( error ) ;
	}

	return NOERR ;
}

tifToMovSet( total )
int total ;
{
	extern int r_waku_clear1( int, int, int ) ;

	EGB_writePage(guiEgbPtr,0);

	r_waku_clear1( 320, 240, 2 ) ;

	MMI_SendMessage( pacWaitDialogId, MM_ATTACH, 1, baseDialogId ) ;

	MMI_SendMessage( pacWaitNumId[0], MM_SETNUMBOX, 5,
		total+svar[0], 0, total+svar[0], 1, 0 ) ;	/* 原画フレーム数設定 */
					/*	var, min, max, delta, ptColumn */
	MMI_SendMessage( pacWaitNumId[1], MM_SETNUMBOX, 5,
		0, 0, total+svar[0], 1, 0 ) ;		/* 圧縮フレーム数設定 */
					/*	var, min, max, delta, ptColumn */

	MMI_SendMessage( pacWaitDialogId, MM_SHOW, 0 ) ;

	return NOERR ;
}

tifToMovReset()
{
	extern int r_waku_del() ;

	EGB_writePage(guiEgbPtr,0);

	MMI_SendMessage( pacWaitDialogId, MM_ERASE, 0 ) ;
	MMI_SendMessage( pacWaitDialogId, MM_DETACH, 0 ) ;

	r_waku_del() ;

	return NOERR ;
}

/*	initDataIRCPAC:pacRoughBar:MJ_SCRLL40の呼び出し関数	*/
int	pacRoughSet(kobj, messId, argc, pev, trigger)
int		kobj ;
int		messId ;
int		argc ;
EVENT	*pev ;
int		trigger ;
{
	int	var, min, max, len, page ;
	MMI_SendMessage( kobj, MM_GETSCROLL, 5,
										&var, &min, &max, &len, &page ) ;
	pacRough = var*8 / 16 ;	/* var * 値の中心値 / バーの中心の値 */
	MMI_SendMessage( pacRoughNumId, MM_SETNUMBOX, 5,
					 pacRough, 0, pacRough, 1, 0 ) ;
					/*	var, min, max, delta, ptColumn */
	MMI_SendMessage( pacRoughNumId, MM_SHOW, 0 ) ;

	return NOERR ;
}

/*	initDataIRCPAC:pacFilterBar:MJ_SCRLL40の呼び出し関数	*/
int	pacFilterSet(kobj, messId, argc, pev, trigger)
int		kobj ;
int		messId ;
int		argc ;
EVENT	*pev ;
int		trigger ;
{
	int	var, min, max, len, page ;
	MMI_SendMessage( kobj, MM_GETSCROLL, 5,
										&var, &min, &max, &len, &page ) ;
	pacFilter = var*8 / 16 ;	/* var * 値の中心値 / バーの中心の値 */
	MMI_SendMessage( pacFilterNumId, MM_SETNUMBOX, 5,
					 pacFilter, 0, pacFilter, 1, 0 ) ;
					/*	var, min, max, delta, ptColumn */
	MMI_SendMessage( pacFilterNumId, MM_SHOW, 0 ) ;

	return NOERR ;
}

/*	initDataIRCPAC:pacTIconId[0]:MJ_TICONL40の呼び出し関数	*/
/*	initDataIRCPAC:pacTIconId[1]:MJ_TICONL40の呼び出し関数	*/
int	pacIdouFunc(kobj, messId, argc, pev, trigger)
int		kobj ;
int		messId ;
int		argc ;
EVENT	*pev ;
int		trigger ;
{
	if( kobj == pacTIconId[0] )
	{
		MTL_setFlagObj( pacTIconId[0], MS_UNSELECT ) ;
		MTL_resetFlagObj( pacTIconId[idouMode+0],
								 (~(MS_UNSELECT | MS_TOGGLE)) ) ;
		MMI_SendMessage( pacTIconId[idouMode+0], MM_SHOW, 0 ) ;
		idouMode = 0 ;
	}
	else
	if( kobj == pacTIconId[1] )
	{
		MTL_setFlagObj( pacTIconId[1], MS_UNSELECT ) ;
		MTL_resetFlagObj( pacTIconId[idouMode+0],
								 (~(MS_UNSELECT | MS_TOGGLE)) ) ;
		MMI_SendMessage( pacTIconId[idouMode+0], MM_SHOW, 0 ) ;
		idouMode = 1 ;
	}
	return NOERR ;
}

/*	initDataIRCPAC:pacOKBtnId:MJ_DBUTTONL40の呼び出し関数	*/
/*	initDataIRCPAC:pacCanBtnId:MJ_DBUTTONL40の呼び出し関数	*/
int	pacOKchk(kobj, messId, argc, pev, trigger)
int		kobj ;
int		messId ;
int		argc ;
EVENT	*pev ;
int		trigger ;
{
	pacOkFlg = 0 ;
	if( kobj == pacOKBtnId )pacOkFlg = TRUE ;
	MMI_SetHaltFlag( TRUE ) ;
	return NOERR ;
}





/* mov2 head read */

mov_head_read(namemov, svar)
char *namemov;
int svar[];
{
	FILE *fp;
	int n, temp, page, size;
	char head[256], para[80];

	if( ( fp = fopen( namemov, "rb" ) ) == NULL )return 1;
	temp = fread( head, 256, 1, fp );
	if( temp < 1 )goto movh10;
	if( DWORD( head+0 ) != 0x32564f4d )goto movh10;
	if( DWORD( head+4 ) != 16 )goto movh10;
	if( DWORD( head+16) != 320 )goto movh10;
	if( DWORD( head+20) != 240 )goto movh10;
	svar[0] = DWORD( head+12 );			/* page  */
	svar[1] = DWORD( head+ 8 );			/* total */
	svar[4] = WORD( head + 32 );			/* 録画領域 */
	svar[5] = WORD( head + 34 );
	svar[6] = WORD( head + 36 );
	svar[7] = WORD( head + 38 );
	DWORD( para+0 ) = (unsigned int)bbuf;
	DWORD( para+4 ) = (unsigned int)rbuf;
	DWORD( para+8 ) = 3;		/* bit0:VRAMページ(0or1)
								   bit1:move_box参照VRAMページ(0or1) */
	DWORD( para+12) = 0;
	n = 0;
movh01:	temp = fread( bbuf, 32, 1, fp );
	if( temp < 1 )goto movh10;
	page = DWORD( bbuf ); size = DWORD( bbuf + 4 );
	if( (unsigned int)size > 500000 )goto movh10;
	temp = fread( bbuf+32, size, 1, fp );
	if( temp < 1 )goto movh10;
	WORD( bbuf+12 ) = 0;		/* wait なし */
	move32( para );
	n++;
	if( n < svar[0] )goto movh01;
	fclose( fp );
	return 0;
movh10:	fclose( fp );
	return 58;
}

mov_save( namemov, path, total, nbuffer )
char *namemov, path[], nbuffer[][16];
int total;
{
	extern int loadtif( char * ) ;

	int i, j, k ;
	int data[14], col[4], temp;
	char tiffname[100];
	char para[256];

	/* 最初のフレームのtifデータを録画領域の変数に */
	if( (total > 0) && (svar[0] == 0) )
	{
		int ret ;

		for( i = 0 ; i<80 ; i++ ){
			tiffname[i] = path[i];
			if( tiffname[i] == (char)0 )break;
		}
//		if( tiffname[i-1] != '\\' )tiffname[i++]='\\';
		for( j=0 ; j<13 ; j++ ){
			tiffname[i++] = nbuffer[0][j];
		}
		ret = loadtif( tiffname );
		EGB_writePage(guiEgbPtr,0);			/* mode3設定 */
		/* セーブ変数に絵の大きさのデータを */
		svar[4] = 0 ;
		svar[5] = 0 ;
		if( ret == NOERR )
		{
			svar[6] = xtif - 1 ;
			if( svar[6] > 319 )svar[6] = 319 ;
			svar[7] = ytif - 1 ;
			if( svar[7] > 239 )svar[7] = 239 ;
		}
		else
		{
			svar[6] = 319 ;
			svar[7] = 239 ;
		}
	}

	for( k = 0 ; k < total ; k++ ){		/* 実行 */
		for( i = 0 ; i<80 ; i++ ){
			tiffname[i] = path[i];
			if( tiffname[i] == (char)0 )break;
		}
//		if( tiffname[i-1] != '\\' )tiffname[i++]='\\';
		for( j=0 ; j<13 ; j++ ){
			tiffname[i++] = nbuffer[k][j];
		}
		temp = loadtif( tiffname );
		if( temp == 0 ){

			int ret ;

			EGB_writePage(guiEgbPtr,0);			/* mode3設定 */
			MMI_SendMessage( pacWaitNumId[1], MM_SETNUMBOX, 5,
				svar[0], 0, svar[0], 1, 0 ) ;	/* 圧縮フレーム数設定 */
					/*	var, min, max, delta, ptColumn */
			MMI_SendMessage( pacWaitNumId[1], MM_SHOW, 0 ) ;

			if( ( ret = mov_save_page(namemov,svar) ) != 0 )
				return ret ;

			EGB_writePage(guiEgbPtr,1);
			DWORD(para+0) = (int)rbuf;
			WORD(para+4) = 0x14;
			WORD(para+6) = 0;
			WORD(para+8) = 0;
			WORD(para+10) = 0 + 319;
			WORD(para+12) = 0 + 239;
			EGB_putBlock( guiEgbPtr, 0, para );
			EGB_writePage(guiEgbPtr,0);
		}
		if( mouseSwCheck() == 3 )return NOERR ;	/* 強制終了 */
	}
	return NOERR;
}

mov_save_trim( svar, cmpmode )
int svar[], cmpmode;
{
	int color, x, y, temp, i, j;

	color = svar[8]+(svar[9] << 5)+(svar[10] << 10);
	for( i=0 ; i<153600 ; i+=4 ){	/* r-buffer top bit clear */
		DWORD( rbuf+i ) &= 0x7fff7fff;
	}
	for( j=0 ; j<245760 ; j+=4 ){	/* vram top bit clear */
		poked( VRAMOFST + j, 0x104, 
						( peekd( VRAMOFST + j, 0x104 ) & 0x7fff7fff ) );
	}
	if( svar[4] > svar[6] ){
		temp = svar[6]; svar[6] = svar[4]; svar[4] = temp;
	}
	if( svar[5] > svar[7] ){
		temp = svar[7]; svar[7] = svar[5]; svar[5] = temp;
	}
	if(    svar[4] == 0	/* full area -> return */
	    && svar[5] == 0
	    && svar[6] == 319
	    && svar[7] == 239
	)return 0;
	for( y=0 ; y<240 ; y++ ){
		for( x=0 ; x<320 ; x++ ){
			if(     x < svar[4]
			    ||  x > svar[6]
			    ||  y < svar[5]
			    ||  y > svar[7]
			){
				i = y*640 + x*2;	/* buffer add */
				j = (y << 10) + (x << 1);	/* vram */
				if( cmpmode ){
					WORD( rbuf+i ) |= 0x8000;
					xorw( VRAMOFST + j, 0x104, 0xffff );
				}
				else pokew( VRAMOFST + j, 0x104, color );
			}
		}
	}
	return 0;
}

mov_save_end( namemov, svar )
char *namemov;
int svar[];
{
	FILE *fps;
	int i, temp, data[2];

	if( svar[0] == 0 )return 0;
	for( i=0 ; i<6 ; i++ ){		/* disk write protect の場合6回必要 */ 
		if( ( fps = fopen( namemov, "r+b" ) ) != NULL )goto save2;
	}
	return 2;
save2:	data[0] = svar[1]; data[1] = svar[0];	/* data長 page */
	fseek( fps, 8, SEEK_SET );
	temp = fwrite( (char *)data, 8, 1, fps );
	fclose( fps );
	if( temp < 1 ){
	/*	remove( namemov );	error */
		return 2;
	}
	return 0;
}

/* save心臓部 */

int scount0;

mov_save_page( namemov, svar )
char *namemov;
int svar[];
{
	int softAdjust[]
	= { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15 };
	int filtAdjust[]
	= { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15 };


	FILE *fps;
	int i, j, k, n, x, y, data, temp;
	int xmin, ymin, xmax, ymax;
	int a1, a2;
	int scount1, cmpmode ;
	char para[64] ;
	char hread[256];	/* for head read */
		/* mov head */
	char mvhead[256]; 
	int mvhead1[] = { 0x32564f4d, 16, 0, 0, 320, 240, 640, 4 };
	int pghead[8];                                   //    ↑main wait

		/* 前の絵と同じ点をカウント */
	scount1 = 0;
	if( svar[4] > svar[6] ){
		temp = svar[6]; svar[6] = svar[4]; svar[4] = temp;
	}
	if( svar[5] > svar[7] ){
		temp = svar[7]; svar[7] = svar[5]; svar[5] = temp;
	}
	xmin = svar[4]; ymin = svar[5]; xmax = svar[6]; ymax = svar[7];
	for( y=ymin ; y<=ymax ; y++ ){
		for( x=xmin ; x<=xmax ; x++ ){
			k = y*640 + x*2;	/* buffer add */
			j = (y << 10) + (x << 1);	/* vram */
			a1 = WORD( rbuf+k );
			a2 = peekw( VRAMOFST + j, 0x104 );
			if( mov_save_cmp_data( a1, a2, svar[2] ) == 0 )
				scount1++; 
		}
	}
	if( scount1 < (scount0 >> 1) )cmpmode = 0;
	else cmpmode = 1;
	scount0 = scount1;
		/* ソフト */
	if( svar[11] ){
		mov_save_soft( svar, bbuf );
		mov_save_filter( softAdjust[ svar[11] ], svar, bbuf );
	}

		/* メインヘッダ */
	if( svar[0] == 0 ){
		svar[0] = 0; svar[1] = 0;
		cmpmode = 0;
		scount0 = (xmax-xmin+1)*(ymax-ymin+1)/8;
			/* 次回から1/16以上同じなら差分 */
		for( k=0 ; k<256 ; k++ )mvhead[k] = (char)0;
		for( k=0 ; k<8 ; k++ )DWORD( mvhead+k*4 ) = mvhead1[k];
		WORD( mvhead + 32 ) = svar[4];
		WORD( mvhead + 34 ) = svar[5];
		WORD( mvhead + 36 ) = svar[6];
		WORD( mvhead + 38 ) = svar[7];
		mvhead[150] = (char)1;	/* タイミングフラグを表示してウエイト */
		for( j=0 ; j<6 ; j++ ){	/* disk write protect の場合6回必要 */ 
			if( (fps=fopen(namemov,"wb") ) != NULL )goto saveH;
		}
		return 2;
	saveH:	fwrite( mvhead, 256, 1, fps );
		fclose( fps );
	}
		/* トリミング */
	mov_save_trim( svar, cmpmode );		/* trimming */
		/* 画面のはみ出した部分をclear */
	EGB_writePage(guiEgbPtr,1);			/* mode10設定 */
	EGB_color(guiEgbPtr,0,0);			/* clear paint */
	EGB_color(guiEgbPtr,2,0);
	EGB_paintMode(guiEgbPtr,0x22);
	EGB_writeMode(guiEgbPtr,0);
	EGB_penSize(guiEgbPtr,1);
	WORD(para+0) = 320;
	WORD(para+2) = 0;
	WORD(para+4) = 511;
	WORD(para+6) = 239;
	EGB_rectangle(guiEgbPtr,para);
	EGB_writePage(guiEgbPtr,0);			/* mode3に書き込み */
	EGB_color(guiEgbPtr,0,0);

/* リフレッシュ */
	if( cmpmode == 0 ){
		for( k=0 ; k<131072 ; k+=4 ){ /* rbufを使って最多色検索 */
			DWORD( rbuf+k ) = 0;	/* clear */
		}
		for( k=0 ; k<76800 ; k++ ){
			data = peekw( VRAMOFST + ((k/320) << 10)+((k%320) << 1), 0x104 );
			j = data << 2;
			DWORD( rbuf+j ) +=1;
		}
		n = 0; data = 0;
		for( k=0 ; k<32768 ; k++ ){
			if( DWORD( rbuf+(k << 2) ) > n ){
				n = DWORD( rbuf+(k << 2) );
				data = k;
			}
		}
		for( k=0 ; k<153600 ; k+=2 ){	/* 塗り潰し */
			WORD( rbuf+k ) = data;
			j = ( (k/640) << 10 ) + ( k % 640 );
			if(
			 mov_save_cmp_data( data,peekw( VRAMOFST +j,0x104),svar[2] ) == 0
			){
				WORD( rbuf+k ) = data | 0x8000;	/* 処理印 */
				xorw( VRAMOFST + j, 0x104, 0xffff );
			}
		}
			/* 孤立した点は処理解除 */
		for( k=2 ; k<153598 ; k+=2 ){
			if( (DWORD( rbuf+k ) & 0x80008000) == 0x8000
			&& (WORD( rbuf+k-2 ) & 0x8000) == 0 ){
				WORD( rbuf+k ) &= 0x7fff;
				j = ( (k/640) << 10 ) + ( k % 640 );
				xorw( VRAMOFST + j, 0x104, 0xffff );
			}
		}

		i = 0;				/* data counter */
		WORD( bbuf+i ) = 3;		/* brock 数 */
		i+=2;
		WORD( bbuf+i ) = 0x1422; i+=2;	/* stosd brock */
		DWORD( bbuf+i ) = 17; i+=4;	/* data size */
		WORD( bbuf+i ) = 1; i+=2;	/* data 数 */
		DWORD( bbuf+i ) = data + ( data << 16 ); i+=4; /* data */
		WORD( bbuf+i ) = 1; i+=2;	/* offset 数 */
		WORD( bbuf+i ) = 0x0000; i+=2;	/* offset */
		WORD( bbuf+i ) = 1; i+=2;	/* data 個数 */
		WORD( bbuf+i ) = 0x0000; i+=2;	/* 下位 address */
		BYTE( bbuf+i ) = 0xff; i+=1;	/* 長さ */
		WORD( bbuf+i ) = 38400; i+=2;
		i = mov_save_stosw1( i, svar );		/* stosw */
			/* 再びくっついてる点は復活 */
		for( k=2 ; k<153598 ; k+=2 ){
		    if( (DWORD( rbuf+k ) & 0x80008000) == 0x80000000
		    || (DWORD( rbuf+k-2 ) & 0x80008000) == 0x8000 ){
			j = ( (k/640) << 10 ) + ( k % 640 );
			a1 = peekw( VRAMOFST + j, 0x104 ); a2 = WORD( rbuf+k );
			if( mov_save_cmp_data( a1, a2, svar[2] ) == 0 
			 && (a2 & 0x8000) == 0 ){
				WORD( rbuf+k ) = a2 | 0x8000;	/* 処理印 */
				xorw( VRAMOFST + j, 0x104, 0xffff );
			}
		    }
		}

		i = mov_save_movsw( i );		/* movsw */
		pghead[0] = svar[0];		/* page page head */
		pghead[1] = i;			/* dsize */
		pghead[2] = 0;			/* ox,oy */
		pghead[3] = 0;			/* wait & loop */
		pghead[4] = 0;			/* リザーブ */
		pghead[5] = 0;			/* sound data1 */
		pghead[6] = 0;			/* sound data2 */
		pghead[7] = 0;			/* sound data3 */
		for( j=0 ; j<6 ; j++ ){	/* disk write protect の場合6回必要 */ 
			if( (fps=fopen( namemov, "r+b" )) != NULL )goto save0;
		}
		return 2;
	save0:	fread( hread, 256, 1, fps );
		fseek( fps, 256+DWORD(hread+8), SEEK_SET );
		fwrite( (char *)pghead, 32, 1, fps );
		fwrite( bbuf, i, 1, fps );
		temp = ferror( fps );
		fclose( fps );
		svar[1] = svar[1] + i + 32;
		goto save10;
	}

/* 差分 */
	i = 0;				/* data counter */
	WORD( bbuf+i ) = 2;
	if( svar[3] )WORD( bbuf+i ) += 1;
	i+=2;
	if( svar[3] ){
		i = mov_save_movebox16( i, svar );
			/* clearしてやり直す */
		for( y=ymin ; y<=ymax ; y++ ){
			for( x=xmin ; x<=xmax ; x++ ){
				j = (y << 10) + (x << 1);	/* vram */
				k = y*640 + x*2;		/* rbuf */
				a1 = peekw( VRAMOFST + j, 0x104 );
				a2 = WORD( rbuf+k );
				if( a1 & 0x8000 )xorw( VRAMOFST + j, 0x104, 0xffff );
				if( a2 & 0x8000 )WORD( rbuf+k ) = a2 & 0x7fff;
			}
		}
	}
		/* フィルター */
//	if( svar[11] )mov_save_filter2( filtAdjust[ svar[11] ], svar, rbuf );
		/* check */
	for( y=ymin ; y<=ymax ; y++ ){
		for( x=xmin ; x<=xmax ; x++ ){
			j = (y << 10) + (x << 1);	/* vram */
			k = y*640 + x*2;		/* rbuf */
			a1 = peekw( VRAMOFST + j, 0x104 );
			a2 = WORD( rbuf+k );
			if( mov_save_cmp_data( a1, a2, svar[2] ) == 0 
			 && (a2 & 0x8000) == 0 ){
				WORD( rbuf+k ) = a2 | 0x8000;	/* 処理印 */
				xorw( VRAMOFST + j, 0x104, 0xffff );
			}
		}
	}
			/* 孤立した点は処理解除 */
	for( k=2 ; k<153598 ; k+=2 ){
		if( (DWORD( rbuf+k ) & 0x80008000) == 0x8000
		&& (WORD( rbuf+k-2 ) & 0x8000) == 0 ){
			WORD( rbuf+k ) &= 0x7fff;
			j = ( (k/640) << 10 ) + ( k % 640 );
			xorw( VRAMOFST + j, 0x104, 0xffff );
		}
	}

	i = mov_save_stosw1( i, svar );		/* stosw */

			/* 再びくっついてる点は復活 */
	for( k=2 ; k<153598 ; k+=2 ){
		if( (DWORD( rbuf+k ) & 0x80008000) == 0x80000000
		|| (DWORD( rbuf+k-2 ) & 0x80008000) == 0x8000 ){
			j = ( (k/640) << 10 ) + ( k % 640 );
			a1 = peekw( VRAMOFST + j, 0x104 ); a2 = WORD( rbuf+k );
			if( mov_save_cmp_data( a1, a2, svar[2] ) == 0 
			 && (a2 & 0x8000) == 0 ){
				WORD( rbuf+k ) = a2 | 0x8000;	/* 処理印 */
				xorw( VRAMOFST + j, 0x104, 0xffff );
			}
		}
	}

	i = mov_save_movsw( i );		/* movsw */
	pghead[0] = svar[0];		/* page page head */
	pghead[1] = i;			/* dsize */
	pghead[2] = 0;			/* ox,oy */
	pghead[3] = 0;			/* wait & loop */
	pghead[4] = 0;			/* リザーブ */
	pghead[5] = 0;			/* sound data1 */
	pghead[6] = 0;			/* sound data2 */
	pghead[7] = 0;			/* sound data3 */
	for( j=0 ; j<6 ; j++ ){	/* disk write protect の場合6回必要 */ 
		if( ( fps = fopen( namemov, "r+b" ) ) != NULL )goto save2;
	}
	return 2;
save2:	fread( hread, 256, 1, fps );
	fseek( fps, 256+DWORD(hread+8), SEEK_SET );
	fwrite( (char *)pghead, 32, 1, fps );
	fwrite( bbuf, i, 1, fps );
	temp = ferror( fps );
	fclose( fps );
	svar[1] = svar[1] + i + 32;
save10:	svar[0]++;
	if( temp ){
	/*	remove( namemov );	disk full */
		return 2;
	}
	return mov_save_end( namemov, svar );
}

/* vramの絵にソフトネスを掛けてbufferに転送 */

mov_save_soft( svar, buffer )
int svar[];
char  *buffer;
{
	int x, y, xk, yk, a, b, r, g, n, k, j;
	int xmin, ymin, xmax, ymax;

	xmin = svar[4]; ymin = svar[5]; xmax = svar[6]; ymax = svar[7];
	for( y=ymin ; y<=ymax ; y++ ){
	    for( x=xmin ; x<=xmax ; x++ ){
		b = 0; r = 0; g = 0;
		n = 0;
		for( yk=y-1 ; yk<y+2 ; yk++ ){
		    for( xk=x-1 ; xk<x+2 ; xk++ ){
			if( yk>=0 && yk<240 && xk>=0 && xk<320 ){
			    j = (yk << 10) + (xk << 1);	/* vram */
			    a = peekw( VRAMOFST + j, 0x104 );
			    b += ( a & 0x1f );
			    r += ( ( a >> 5 ) & 0x1f );
			    g += ( ( a >> 10 ) & 0x1f );
			    n++;
			}
		    }
		}
		if( n ){
			b = ( b + (b % n ) ) / n;
			r = ( r + (r % n ) ) / n;
			g = ( g + (g % n ) ) / n;
		}
		k = y*640 + x*2;	/* buffer add */
		WORD( buffer+k ) = b + (r << 5) + (g << 10);
	    }
	}
	return 0;
}

/* vramの絵にフィルターを掛ける(bufferをかぶせる) */

mov_save_filter( flt, svar, buffer )
int flt, svar[];
char *buffer;
{
	int j, k, x, y, flt1, flt2, flt3;
	int a1, a2, b1, r1, g1, b2, r2, g2;
	int xmin, ymin, xmax, ymax;
	int filt[][19] = {
		{ -9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9 },
		{ -9,-8,-7,-6,-5,-4,-3,-2, 0,0,0,2,3,4,5,6,7,8,9 },
		{ -9,-8,-7,-6,-5,-4,-3,-1, 0,0,0,1,3,4,5,6,7,8,9 },
		{ -9,-8,-7,-6,-5,-4,-2,-1, 0,0,0,1,2,4,5,6,7,8,9 },
		{ -9,-8,-7,-6,-5,-4,-2, 0, 0,0,0,0,2,4,5,6,7,8,9 },
		{ -9,-8,-7,-5,-4,-2,-1, 0, 0,0,0,0,1,2,4,5,7,8,9 },
	};
	int f1[] = { 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5 };
	int f2[] = { 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5 };
	int f3[] = { 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5 };


		/* フィルター */
	if( flt < 0 )flt = 0;
	if( flt > 15 )flt = 15;
	flt1 = f1[ flt ];
	flt2 = f2[ flt ];
	flt3 = f3[ flt ];
	xmin = svar[4]; ymin = svar[5]; xmax = svar[6]; ymax = svar[7];
	if( flt )
		for( y=ymin ; y<=ymax ; y++ ){
			for( x=xmin ; x<=xmax ; x++ ){
				k = y*640 + x*2;	/* buffer add */
				j = (y << 10) + (x << 1);	/* vram */
				a1 = WORD( buffer+k );
				a2 = peekw( VRAMOFST + j, 0x104 );
				b1 = a1 & 0x1f; b2 = a2 & 0x1f;
				r1 = (a1 >> 5) & 0x1f; r2 = (a2 >> 5) & 0x1f;
				g1 =(a1 >> 10) & 0x1f; g2 =(a2 >> 10) & 0x1f;
				if( (b2-b1 > -10) && (b2-b1 < 10) )
					b2 = b1 + filt[ flt1 ][b2-b1+9];
				if( (r2-r1 > -10) && (r2-r1 < 10) )
					r2 = r1 + filt[ flt2 ][r2-r1+9];
				if( (g2-g1 > -10) && (g2-g1 < 10) )
					g2 = g1 + filt[ flt3 ][g2-g1+9];
				pokew( VRAMOFST +j, 0x104, b2 + (r2 << 5) + (g2 << 10));
			}
		}
	return 0;
}

/* bが等しくないとrを行わない b,rが等しくないとgを行わない */

mov_save_filter2( flt, svar, buffer )
int flt, svar[];
char *buffer;
{
	int j, k, x, y, flt1, flt2, flt3;
	int a1, a2, b1, r1, g1, b2, r2, g2;
	int xmin, ymin, xmax, ymax;
	int filt[][19] = {
		{ -9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9 },
		{ -9,-8,-7,-6,-5,-4,-3,-2, 0,0,0,2,3,4,5,6,7,8,9 },
		{ -9,-8,-7,-6,-5,-4,-3,-1, 0,0,0,1,3,4,5,6,7,8,9 },
		{ -9,-8,-7,-6,-5,-4,-2,-1, 0,0,0,1,2,4,5,6,7,8,9 },
		{ -9,-8,-7,-6,-5,-4,-2, 0, 0,0,0,0,2,4,5,6,7,8,9 },
		{ -9,-8,-7,-5,-4,-2,-1, 0, 0,0,0,0,1,2,4,5,7,8,9 },
	};
	int f1[] = { 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5 };
	int f2[] = { 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5 };
	int f3[] = { 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5 };

		/* フィルター */
	if( flt < 0 )flt = 0;
	if( flt > 15 )flt = 15;
	flt1 = f1[ flt ];
	flt2 = f2[ flt ];
	flt3 = f3[ flt ];
	xmin = svar[4]; ymin = svar[5]; xmax = svar[6]; ymax = svar[7];
	if( flt )
		for( y=ymin ; y<=ymax ; y++ ){
			for( x=xmin ; x<=xmax ; x++ ){
				k = y*640 + x*2;	/* buffer add */
				j = (y << 10) + (x << 1);	/* vram */
				a1 = WORD( buffer+k );
				a2 = peekw( VRAMOFST + j, 0x104 );
				b1 = a1 & 0x1f; b2 = a2 & 0x1f;
				r1 = (a1 >> 5) & 0x1f; r2 = (a2 >> 5) & 0x1f;
				g1 =(a1 >> 10) & 0x1f; g2 =(a2 >> 10) & 0x1f;
				if( (b2-b1 > -10) && (b2-b1 < 10) )
					b2 = b1 + filt[ flt1 ][b2-b1+9];
				if( (r2-r1 > -10)
				 && (r2-r1 < 10)
				 && (b1 == b2) )
					r2 = r1 + filt[ flt2 ][r2-r1+9];
				if( (g2-g1 > -10)
				 && (g2-g1 < 10)
				 && (b1 == b2)
				 && (r1 == r2) )
					g2 = g1 + filt[ flt3 ][g2-g1+9];
				if( (b1==b2) && (r1==r2) && (g1==g2) )
					pokew( VRAMOFST +j, 0x104, b2 + (r2 << 5) + (g2 << 10));
			}
		}
	return 0;
}

/* 平均化したデータをrbufに書き込む */

mov_save_stosw1_write( p, svar )
int p;
int svar[];
{
	int i, j, k, n, m, data, addre1, addre2, len;
	int a1, a2, vadd;

	data = WORD( bbuf + p ) | 0x8000;
	p += 2;
	n = WORD( bbuf + p );
	p += 2;
	if( n ){
	    for( i=0 ; i<n ; i++ ){
		addre1 = WORD( bbuf + p ) << 16;
		p += 2;
		m = WORD( bbuf + p );
		p += 2;
		if( m ){
		    for( j=0 ; j<m ; j++ ){
			addre2 = addre1 + WORD( bbuf + p );
			p += 2;
			len = BYTE( bbuf + p );
			p += 1;
			if( len == 0xff ){
				len = WORD( bbuf + p );
				p += 2;
			}
			if( len == 0xffff ){
				len = DWORD( bbuf + p );
				p += 4;
			}
			if( len ){
			    for( k=0 ; k<len ; k++ ){
				WORD( rbuf + addre2 + k*2 ) = data;
			    }
			}
				/* 両端okなら処理済みに */
			k = addre2 - 2;
			if( k > 0 && k < 153600 ){
			    vadd = ( (k/640) << 10 ) + ( k % 640 );
			    a1 = peekw( VRAMOFST + vadd, 0x104 ); a2 = WORD( rbuf+k );
			    if( mov_save_cmp_data( a1, a2, svar[2] ) == 0 
			     && (a2 & 0x8000) == 0 ){
				WORD( rbuf+k ) = a2 | 0x8000;
				xorw( VRAMOFST + vadd, 0x104, 0xffff );
			    }
			}
			k = addre2 + len*2;
			if( k > 0 && k < 153600 ){
			    vadd = ( (k/640) << 10 ) + ( k % 640 );
			    a1 = peekw( VRAMOFST + vadd, 0x104 ); a2 = WORD( rbuf+k );
			    if( mov_save_cmp_data( a1, a2, svar[2] ) == 0 
			     && (a2 & 0x8000) == 0 ){
				WORD( rbuf+k ) = a2 | 0x8000;
				xorw( VRAMOFST + vadd, 0x104, 0xffff );
			    }
			}
		    }
		}
	    }
	}
	return 0;
}

/* store 最初にdataを読み込むtype & data平均化付き(1992 1.17) */

mov_save_stosw1( i, svar )
int i;
int svar[];
{
	int p1, p2, p3, p4, p5, p6;
	int j, j1, j2, j3;
	int k, k1;
	int data;
	int a1, a2;
	int n1, n2, n3;
	int bt, rt, gt, nt, dt;		/* data 平均値用 変数 */

	WORD( bbuf+i ) = 0x1222; i+=2;	/* stosw brock */
	p1 = i; i+=4;			/* size point */
	p2 = i; i+=2;			/* data count point */
	n1 = 0;				/* data count */
	for( j1=0 ; j1<153600 ; j1+=2 ){
	    if( WORD( rbuf+j1 ) & 0x8000 )goto stos03;	/* 処理済skip */
	    j = ( (j1/640) << 10 ) + ( j1 % 640 );	/* j = vram address */
	    data = peekw( VRAMOFST + j, 0x104 );
	    if(
	      mov_save_skip_check6( data, j1, svar )
	    )goto stos03;		/* skip check */
	    bt = 0; rt = 0; gt = 0; nt = 0;		/* for data 平均 */
	    p3 = i;			/* data top point */
	    WORD( bbuf+i ) = data; i+=2;	/* data */
	    p4 = i; i+=2;		/* offset count point */
	    n2 = 0;			/* offset count */
	    for( j2=0 ; j2<3 ; j2++ ){ /* offset loop */
		p5 = i;			/* offset top point */
		WORD( bbuf+i ) = j2; i+=2;	/* offset */
		p6 = i; i+=2;		/* d-address count point */
		n3 = 0;			/* d-address count */
		k = 0; k1 = 0;		/* data長count係数 */
		for( j3=0x10000*j2 ; j3<0x10000*(j2+1) ; j3+=2 ){
		    if( j3 >= 153600 )break;
		    a2 = WORD( rbuf+j3 );
		    if( a2 & 0x8000 ){			/* 処理済skip */
			if( k ){
			    i = i + k1;
			    k = 0; k1 = 0;
			}
			goto stos01;
		    }
	 	    j = ( (j3/640) << 10 ) + ( j3 % 640 );
		    a1 = peekw( VRAMOFST + j, 0x104 );
		    if( (a2 & 0x8000) == 0		 /* 手つかず */
		        && mov_save_cmp_data( data, a1, svar[2] ) == 0 
		        				/* 同色と認め */ 
		    ){
			if( k == 0 )if( 
			  mov_save_skip_check4(data,j3,svar)
			)goto stos01;
			k++;

				/* for data 平均 */
			bt = bt + ( a1 & 0x1f );
			rt = rt + ( (a1 >> 5) & 0x1f );
			gt = gt + ( (a1 >> 10) & 0x1f );
			nt++;

			WORD( rbuf+j3 ) = 0x8000 | data;	/* 処理印 */
			xorw( VRAMOFST + j, 0x104, 0xffff );
			if( k == 1 ){
			    n3++;
			    WORD( bbuf+i ) = ( j3 & 0xffff );
			}
			if( k<0xff ){
			    BYTE( bbuf+i+2 ) = k;
			    k1 = 1+2;
			}
			if( (k>=0xff) && (k<0xffff) ){
			    BYTE( bbuf+i+2 ) = 0xff;
			    WORD( bbuf+i+3 ) = k;
			    k1 = 3+2;
			}
			if( k>=0xffff ){
			    BYTE( bbuf+i+2 ) = 0xff;
			    WORD( bbuf+i+3 ) = 0xffff;
			    DWORD( bbuf+i+5 ) = k;
			    k1 = 7+2;
			}
		    }
		    else {
			if( k ){
			    i = i + k1;
			    k = 0; k1 = 0;
			}
		    }
	    stos01: ;
		}
	stos02:	i = i + k1;
		WORD( bbuf+p6 ) = n3;
		if( n3 )n2++;
		else i = p5;
	    }
	    WORD( bbuf+p4 ) = n2;
	    if( n2 ){
		n1++;

		if( nt ){	/* for data 平均 */
		    dt =  ( (bt + bt % nt) / nt )
		      + ( ( (rt + rt % nt) / nt ) << 5 )
		      + ( ( (gt + gt % nt) / nt ) << 10 );
		    WORD( bbuf + p3 ) = dt;
		    mov_save_stosw1_write( p3, svar );
		}

	    }
	    else i = p3;
    stos03: ;
	}
	WORD( bbuf+p2 ) = n1;
	if( n1 == 0 )i = p2;
	DWORD( bbuf+p1 ) = i - p2;
	return i;
}

mov_save_skip_check2( data, n, svar )
int data, n;
int svar[];
{			/* 4つdataと同じ色が続くもの以外はスキップ */
	int a, b, i, j, k;

	if( n > 153588 )return 1;
	if( WORD( rbuf+n ) & 0x8000 )return 1;
	for( i=0 ; i<4 ; i++ ){
		k = n + (i << 1);
		j = ( (k/640) << 10 ) + ( k % 640 );
		a = peekw( VRAMOFST + j, 0x104 );
		b = WORD( rbuf + k );
		if( mov_save_cmp_data( data, a, svar[2]) )return 1;
	}
	return 0;
}

/* skip_check1 = 1:skip ( for stosw ) */

mov_save_skip_check4( data, n, svar )
int data, n;
int svar[];
{			/* 4つdataと同じ色が続くもの以外はスキップ */
	int a, b, i, j, k;

	if( n > 153588 )return 1;	/* ↓処理済直後はok */
	if( n && ( (DWORD( rbuf+n-2 ) & 0x80008000) == 0x8000 ) )return 0;
	if( WORD( rbuf+n ) & 0x8000 )return 1;
	for( i=0 ; i<4 ; i++ ){
		k = n + (i << 1);
		j = ( (k/640) << 10 ) + ( k % 640 );
		a = peekw( VRAMOFST + j, 0x104 );
		b = WORD( rbuf + k );
		if( b & 0x8000 )return 0;
		if( mov_save_cmp_data( data, a, svar[2]) )return 1;
	}
	return 0;
}

mov_save_skip_check6( data, n, svar )
int data, n;
int svar[];
{			/* 6つdataと同じ色が続くもの以外はスキップ */
	int a, b, i, j, k;

	if( n > 153588 )return 1;
	if( DWORD( rbuf+n ) & 0x80008000 )return 1;
	if( DWORD( rbuf+n+4 ) & 0x80008000 )return 1;
	if( DWORD( rbuf+n+8 ) & 0x80008000 )return 1;
	for( i=0 ; i<6 ; i++ ){
		k = n + (i << 1);
		j = ( (k/640) << 10 ) + ( k % 640 );
		a = peekw( VRAMOFST + j, 0x104 );
		b = WORD( rbuf + k );
		if( mov_save_cmp_data( data, a, svar[2]) )return 1;
	}
	return 0;
}

/* movsw */

mov_save_movsw( i )
int i;
{
	int p1, p4, p5, p6;
	int j, j2, j3, j4;
	int k, k1, k2;
	int a1, a2;
	int n2, n3;

	WORD( bbuf+i ) = 0x2222; i+=2;	/* movsw brock */
	p1 = i; i+=4;			/* size point */
	p4 = i; i+=2;		/* offset count point */
	n2 = 0;			/* offset count */
	for( j2=0 ; j2<3 ; j2++ ){ /* offset loop */
	    p5 = i;			/* offset top point */
	    WORD( bbuf+i ) = j2; i+=2;	/* offset */
	    p6 = i; i+=2;		/* d-address count point */
	    n3 = 0;			/* d-address count */
	    k = 0; k1 = 0;		/* data長count係数 */
	    for( j3=0x10000*j2 ; j3<0x10000*(j2+1) ; j3+=2 ){
		if( j3 >= 153600 )break;
	 	j = ( (j3/640) << 10 ) + ( j3 % 640 );		/* vram add */
		a1 = peekw( VRAMOFST + j, 0x104 ); a2 = WORD( rbuf+j3 );
		if( (a2 & 0x8000) == 0 ){
		    k++;
		    WORD( rbuf+j3 ) = 0x8000 | a1;		/* 処理印 */
		    xorw( VRAMOFST + j, 0x104, 0xffff );
		    if( k == 1 ){
			n3++;
			k2 = j3;			/* address記憶 */
			WORD( bbuf+i ) = ( j3 & 0xffff );
		    }
		    if( k<0xff ){
			BYTE( bbuf+i+2 ) = k;
			k1 = 1+2;
		    }
		    if( (k>=0xff) && (k<0xffff) ){
			BYTE( bbuf+i+2 ) = 0xff;
			WORD( bbuf+i+3 ) = k;
			k1 = 3+2;
		    }
		    if( k>=0xffff ){
			BYTE( bbuf+i+2 ) = 0xff;
			WORD( bbuf+i+3 ) = 0xffff;
			DWORD( bbuf+i+5 ) = k;
			k1 = 7+2;
		    }
		}
		else {
		    if( k ){
			i = i + k1;
			k = 0; k1 = 0;
			for( j4=k2 ; j4<j3 ; j4+=2 ){ /* data write */
			    WORD( bbuf+i ) = WORD( rbuf+j4 ) & 0x7fff;
			    i+=2;
			}
		    }
		}
	movs01: ;
	    }
    movs02: if( k ){
		i = i + k1;
		k = 0; k1 = 0;
		for( j4=k2 ; j4<j3 ; j4+=2 ){ /* data write */
		    WORD( bbuf+i ) = WORD( rbuf+j4 ) & 0x7fff;
		    i+=2;
		}
	    }
	    WORD( bbuf+p6 ) = n3;
	    if( n3 )n2++;
	    else i = p5;
 	}
	WORD( bbuf+p4 ) = n2;
	if( n2 == 0 )i = p4;
	DWORD( bbuf+p1 ) = i - p4;
	return i;
}

/* move box ( 16*16dot )指定されたboxを転送 */

mov_save_movebox16( i, svar )
int i, svar[];
{
	int p1, p2, n;
	int j, j2, j3;
	int xmin, xmax, ymin, ymax, x, y, x1, y1, x2, y2, kx, ky, d;
	int max, a, a1, a2, b, r, g, cr, cb, yu, temp, temp2;
	int bfaddr, rbaddr, vraddr;
	char *offset1, *offset2;
	char vyuv[1024];		/* vram YUV data */

	offset1 = bbuf+0x1000;	/* 旧画面データをchar *offset1にもう1枚作る */
	for( j=0 ; j<153600 ; j+=4 )DWORD( offset1+j ) = DWORD( rbuf+j );
	offset2 = bbuf+0x30000;	/* 旧画面データのYUV data */
		/* rgb data (offset1) を yuv data (offset2) に */
	for( j=0 ; j<76800 ; j++ ){
		a = WORD( offset1 + (j << 1) );
		b = a & 0x1f;
		r = (a >> 5) & 0x1f;
		g = (a >> 10) & 0x1f;
			/* G,R,BをY,Cr,Cbに変換 */
		cr = -107*g + 128*r - 21*b + 3968;	/* 0〜256*31 */
		cb = -85*g - 43*r + 128*b + 3968;
		yu = ( 150*g + 77*r + 37*b ) >> 4;
			/* Cr(8), Cb(8), Y(16) */
		DWORD( offset2 +(j << 2) )
		 = (cr >> 5) + ((cb << 3)& 0x0ff00) + (yu << 16);
	}

	WORD( bbuf+i ) = 0x3010; i+=2;	/* move box 16 */
	p1 = i; i+=4;			/* size point */
	p2 = i; i+=2;		/* data 個数 count point */
	n = 0;			/* data 個数 count */
		/* trimming area を はずすためのもの */
	xmin = 16*( svar[4]/16 ); if( svar[4]%16 )xmin += 16;
	xmax = 16*( svar[6]/16 ); if( svar[6]%16 == 15 )xmax += 1;
	ymin = 16*( svar[5]/16 ); if( svar[5]%16 )ymin += 16;
	ymax = 16*( svar[7]/16 ); if( svar[7]%16 == 15 )ymax += 1;
	for( y=ymin ; y<ymax ; y+=16 ){
	    for( x=xmin ; x<xmax ; x+=16 ){
			/* vram YUV */
		vraddr = y*1024 + x*2; 	/* vram address */
		j = 0;			/* count vyuv */
		for( j2=0 ; j2<16 ; j2++ ){
		    for( j3=0 ; j3<32 ; j3+=2 ){
			a = peekw( VRAMOFST + vraddr+j3, 0x104 );
			b = a & 0x1f;
			r = (a >> 5) & 0x1f;
			g = (a >> 10) & 0x1f;
				/* G,R,BをY,Cr,Cbに変換 */
			cr = -107*g + 128*r - 21*b + 3968;	/* 0〜256*31 */
			cb = -85*g - 43*r + 128*b + 3968;
			yu = ( 150*g + 77*r + 37*b ) >> 4;
				/* Cr(8), Cb(8), Y(16) */
			DWORD( vyuv +j )
			 = (cr >> 5) + ((cb << 3) & 0x0ff00) + (yu << 16);
			j+=4;
		    }
		    vraddr += 1024;
		}
		temp2 = mov_save_cmp_box16( offset2, x, y, vyuv, svar[2] );
		if( temp2 > 255-8 )goto mov02;
		max = temp2;
		kx = x; ky = y;
			/* ずらして調べる */
		x1 = x; y1 = y;
		for( d=svar[3] ; d>0 ; d-- ){
		  for( j2 = -1 ; j2 <= 1 ; j2++ ){
		     for( j3 = -1 ; j3 <= 1 ; j3++ ){
			x2 = x1 + j3*d;
			y2 = y1 + j2*d;
			if( x2 < 0 )x2 = 0;	/* はみ出しを切る */
			if( x2 > 304 )x2 = 304;
			if( y2 < 0 )y2 = 0;
			if( y2 > 224 )y2 = 224;
			temp
			= mov_save_cmp_box16(
			 offset2, x2, y2, vyuv, svar[2] );
			if( temp > max ){
			    max = temp;
			    kx = x2; ky = y2;
			}
		     }
		  }
		  x1 = kx; y1 = ky;
		}
			/* 大まかに調べる */
		x1 = x - 32; if( x1 < 0 )x1 = 0;
		x2 = x + 32; if( x2 > 304 )x2 = 304;
		y1 = y - 32; if( y1 < 0 )y1 = 0;
		y2 = y + 32; if( y2 > 224 )y2 = 224;
		for( j2 = x1 ; j2 <= x2 ; j2+=16 ){
		    for( j3 = y1 ; j3 <= y2 ; j3+=16 ){
			temp
			= mov_save_cmp_box16( offset2, j2, j3, vyuv, svar[2] );
			if( temp > max ){
			    max = temp;
			    kx = j2; ky = j3;
			}
		    }
		}
		if( max > temp2+8 ){
		    DWORD( bbuf+i ) = y*640 + x*2; i+=4;
		    WORD( bbuf+i ) = kx; i+=2;
		    WORD( bbuf+i ) = ky; i+=2;
		    n++;
		    bfaddr = ky*640 + kx*2; 	/* offset1 相対 address */
		    rbaddr = y*640 + x*2; 	/* rbuf 相対 address */
		    vraddr = y*1024 + x*2; 	/* vram address */
		    for( j2=0 ; j2<16 ; j2++ ){
			for( j3=0 ; j3<32 ; j3+=2 ){
			    a1 = peekw( VRAMOFST + vraddr+j3, 0x104 );
			    a2 = WORD( offset1+bfaddr+j3 ) & 0x7fff;
			    WORD( rbuf+rbaddr+j3 ) = a2;
			    if( mov_save_cmp_data( a1, a2, svar[2] ) == 0 
		 	    && (a1 & 0x8000) == 0 ){
				WORD( rbuf+rbaddr+j3 ) = a2 | 0x8000;
				xorw( VRAMOFST + vraddr+j3, 0x104, 0xffff );
			    }
			}
			bfaddr+=640; rbaddr+=640; vraddr+=1024;
		    }
	    mov02:  ;
		}
	    }
	}
	WORD( bbuf+p2 ) = n;
	if( n == 0 )i = p2;
	DWORD( bbuf+p1 ) = i - p2;
	return i;
}

/* YUV data buffer の char buffer(320*240)[開始座標(x,y)]と
char *vyuv(16*16)の中でYUV判定で同じものを数える */

mov_save_cmp_box16( buffer, x, y, vyuv, rate )
char *buffer, *vyuv;
int x, y, rate;
{
	int d1, d2, i, j, n, rate2;

	buffer = buffer + 1280*y + 4*x;
	n = 0; rate2 = rate*rate;
	for( j=0 ; j<16 ; j++ ){
		for( i=0 ; i<64 ; i+=4 ){
		    d1 = (WORD( buffer+i+2 ) - WORD( vyuv+2 ));
		    if( d1 > rate )goto cmp01;
		    if( d1 < -rate )goto cmp01;
		    d1 = BYTE( buffer+i ) - BYTE( vyuv );
		    d2 = BYTE( buffer+i+1 ) - BYTE( vyuv+1 );
		    if( d1*d1 + d2*d2 <= rate2 )n++;
	    cmp01:  vyuv += 4;
		}
		buffer += 1280;
	}
	return n;
}

/* Y,Cr,CbによるCOLCOR DATA比較法 91 7 24 */

mov_save_cmp_data( a, b, rate )
int a, b, rate;
{
	int b1,r1,g1, b2,r2,g2, d1, d2;

	if( (a & 0x7fff) == (b & 0x7fff) )return 0; /* 明白なものは処理 */
	else if( rate == 0 )return 1;
		/* G,R,B算出 */
	b1 = a & 0x1f; b2 = b & 0x1f;
	r1 = (a >> 5) & 0x1f; r2 = (b >> 5) & 0x1f;
	g1 = (a >> 10) & 0x1f; g2 = (b >> 10) & 0x1f;
		/* G,R,BをY,Cr,Cbに変換 & 判定 */
	d1 = ( 150*(g2 - g1) + 77*(r2 - r1) + 37*(b2 - b1) ) >> 4;
	if( d1 > rate )return 1;
	if( d1 < -rate )return 1;
	d1 = ( -107*(g2-g1) + 128*(r2-r1) - 21*(b2-b1) ) >> 5;
	d2 = ( -85*(g2 -g1) - 43*(r2 -r1) + 128*(b2 -b1) ) >> 5;
	if( d1*d1 + d2*d2 > rate*rate )return 1;
	else return 0;
}









