/*
	ARTemis (Graphic Editor for FM-TOWNS)
	(c) MATSUUCHI Ryosuke 1992

	sub.c

	補助処理モジュール


	page_menu			書き込みページをメニュー用ページに
	page_edit			書き込みページを描画用ページに

	trans_fname_ext		ファイル名の拡張子を置き換える
	getfsize			あるファイルの大きさを得る
	resetfattr			ファイルの属性をクリアする

	cbuf_init			濃度バッファ・初期化
	cbuf_clear			濃度バッファ・クリア
	cbuf_adrs			濃度バッファ・指定座標のアドレス取得
	cbuf_getlinesize	
	cbuf_mix

	scrollForCsr		カーソル座標が画面内にくるようスクロール
	limitCsrPos			カーソル座標の制限

	area_init			領域指定処理の初期化
	area_input			矩形／ポリゴンによる領域の入力
	area_chkxy			ある座標が、指定領域内かどうかを調べる
	area_chkxy2			(x,y)-(x+1,y+1)が、指定領域内かどうかを調べる
	area_chkxylen		ある座標から右に何ドット同じフラグが連続しているか
	area_getboundxy		指定領域を囲む最小の矩形を得る

	hline_func			マスクされていない部分だけに描画する
*/

#include <stdio.h>
#include <stdefs.h>
#include <egb.h>
#include <malloc.h>
#include <stdlib.h>
#include <msdos.cf>
#include <memory.h>
// #include <interrup.cf>
#include <math.h>
#include <dos.h>

void FM_ResetVector(void);
void FM_SetVector(void);

#include "ge.h"
#include "plt16.h"
#include "dispman.h"
#include "imageman.h"
#include "mask.h"

/*--------------------------------------------------------*/
/*                     ページ切り換え                     */
/*--------------------------------------------------------*/


void page_menu()
{
	gwrtpage(0);
}


void page_edit()
{
	if (!DMgetifonepage())
		gwrtpage(1);
	else
		gwrtpage(0);
}

/*--------------------------------------------------------*/
/*                 ファイルの大きさを得る                 */
/*--------------------------------------------------------*/

int getfsize(char *fname)
{
	struct find_t dirbuf;
	if (_dos_findfirst(fname, _A_NORMAL, &dirbuf) == 0)
		return dirbuf.size;
	else
		return -1;
}

/*--------------------------------------------------------*/
/*               ファイルの属性をクリアする               */
/*--------------------------------------------------------*/

int resetfattr(char *fname)
{
	if (_dos_setfileattr(fname, _A_ARCH | _A_NORMAL) == 0)
		return 0;
	else
		return -1;
}

bool fexist(char *fname)
{
	unsigned int b;
	if (_dos_getfileattr(fname, &b) == 0)
		return YES;
	else
		return NO;
}

/*--------------------------------------------------------*/
/*                       文字列操作                       */
/*--------------------------------------------------------*/


char *trans_fname_ext(char *fname, char *newext)
/*
	ファイル名 fname の拡張子を newext に置き換えたファイル名を返す
*/
{
	static char path_buf[_MAX_PATH];
	char drive[_MAX_DRIVE], dir[_MAX_DIR], basename[_MAX_FNAME], ext[_MAX_EXT];
	_splitpath(fname, drive, dir, basename, ext);
	_makepath(path_buf, drive, dir, basename, newext);
	return path_buf;
}


void add_fname_ext(char *buf, char *fname, char *newext)
/*
	ファイル名 fname に拡張子が無い場合、newext を拡張子として加える
*/
{
	char drive[_MAX_DRIVE], dir[_MAX_DIR], basename[_MAX_FNAME], ext[_MAX_EXT];
	_splitpath(fname, drive, dir, basename, ext);
	if (ext[0] == '\0')
		_makepath(buf, drive, dir, basename, newext);
	else
		_makepath(buf, drive, dir, basename, ext);
}


/*--------------------------------------------------------*/
/*                   濃度バッファの扱い                   */
/*--------------------------------------------------------*/


//　濃度バッファは、１ドットが１バイトに対応するバッファ。
//  各バイトには、「(描画したい濃度)-1」の値(0..255)が入る。
// ★★ 将来、編集バッファサイズ変更機能を加えたときはこのままではダメ


static	char*	cbuf = NULL;
static	int		cbuf_xsize,cbuf_ysize;


int cbuf_init()
{
	cbuf_xsize = EIMgetxsize();
	cbuf_ysize = EIMgetysize();
	if ((cbuf = malloc(cbuf_xsize*cbuf_ysize)) == NULL)
		return -1;
	memset(cbuf,0,cbuf_xsize*cbuf_ysize);
	return 0;
}


void cbuf_clear()
{
	memset(cbuf,0,cbuf_xsize*cbuf_ysize);
}


char *cbuf_adrs(int x, int y)
{
	return cbuf+y*cbuf_xsize+x;
}


int cbuf_getlinesize()
{
	return cbuf_xsize;
}


int cbuf_mix(int c0, int rate, int maxconc)
{
	int c;
	if (rate == 0 || c0 >= maxconc)
		return c0;
	else if (rate == 256)
		return maxconc;
	c = (c0 * (256-rate) + maxconc * rate + 255) >> 8;
	if (c == c0)
		return _min(c+1,maxconc);
	else
		return _min(c,maxconc);
}


/*--------------------------------------------------------*/
/*                       スクロール                       */
/*--------------------------------------------------------*/


void scrollForCsr(int xlen,int ylen)
// (ms.x,ms.y)-len(xlen,ylen) の範囲が画面内にくるようにスクロール
{
	int dispx,dispy,dispxlen,dispylen;
	int zr=DMimage_getzoomrate();
	DMimage_getdispxy(&dispx,&dispy);
	DMimage_getdispxylen(&dispxlen,&dispylen);
	int pre_dispx,pre_dispy;
	bool mschg;
	pre_dispx = dispx, pre_dispy = dispy;
	mschg = NO;
	while (ms.x+xlen-1>=DMgetxsize()) {
		if (dispx + dispxlen < EIMgetxsize())
			ms.x -= zr,  dispx++,  mschg = YES;
		else
			ms.x=DMgetxsize()-xlen,  mschg = YES;
	}
	while (ms.x<0) {
		if (dispx > 0)
			ms.x += zr,  dispx--,  mschg = YES;
		else
			ms.x=0,  mschg = YES;
	}
	while (ms.y+ylen-1>=DMgetysize()) {
		if (dispy + dispylen < EIMgetysize())
			ms.y -= zr,  dispy++,  mschg = YES;
		else
			ms.y=DMgetysize()-ylen,  mschg = YES;
	}
	while (ms.y<0) {
		if (dispy > 0)
			ms.y += zr,  dispy--, mschg = YES;
		else
			ms.y=0,  mschg = YES;
	}
	if (mschg)
		mous_setpos(&ms, ms.x, ms.y);
	if (pre_dispx!=dispx || pre_dispy!=dispy)
		DMimage_setdispxy(dispx,dispy);
}


void limitCsrPos()	// カーソルの座標の制限処理
{
	bool mschg = NO;
	if (ms.x < 0)
		ms.x = 0, mschg = YES;
	else if (ms.x >= DMgetxsize())
		ms.x = DMgetxsize()-1, mschg = YES;
	if (ms.y < 0)
		ms.y = 0, mschg = YES;
	else if (ms.y > DMgetysize())
		ms.y = DMgetysize()-1, mschg = YES;
	if (mschg)
		mous_setpos(&ms, ms.x, ms.y);
}


/*--------------------------------------------------------*/
/*             矩形／ポリゴンによる領域の入力             */
/*--------------------------------------------------------*/


static char *area_buf = NULL;
static bool areasizevar = NO;	// 領域指定バッファの縦横サイズが可変かどうか
static int areaxlen, areaylen;	// areasizevar=YES時のバッファの縦横サイズ
static int ax1,ay1,ax2,ay2;		// 指定領域を囲む最小矩形
#define	XBUFMAX		10			/* 1ラインにつき､x 座標をいくつ記憶するか */
#define	RIGHTMAX	0x7fff
typedef short int	areapos;
static areapos **xbuf = NULL;	// ポリゴン指定用ワーク
#define	MAXP	1024
static areapos *px=NULL,*py=NULL;  // ポリゴンの輪郭保存用
static short int pnum;

#define	AREAXLEN	512

int area_init()
// 返値: 0=成功  0以外=メモリ不足
{
	int size;
	if (EIMgetxsize() <= AREAXLEN)
		areasizevar = NO, areaxlen = AREAXLEN;
	else
		areasizevar = YES, areaxlen=(EIMgetxsize()+7)&0xffff8;
	areaylen = EIMgetysize();
	size = (areaxlen / 8) * areaylen;
	if (area_buf == NULL)
	{
		if ((area_buf = calloc(1,size)) == NULL)
		{
			DEBUG_MSG("領域指定バッファ用メモリ領域　確保失敗");
			return -1;
		}
		else
			DEBUG_MSG("領域指定バッファ用メモリ領域　確保成功");
	}
	if (xbuf == NULL)
	{
		if ((xbuf = (areapos**)malloc(sizeof(areapos*)*areaylen)) == NULL)
			return -1;
		memset(xbuf, 0, sizeof(areapos*) * areaylen);
	}
	if (xbuf[0] == NULL) {
		bool error = NO;
		int i;
		for (i=0; i<areaylen; i++)
		{
			if ((xbuf[i] = (areapos*)malloc(sizeof(areapos)*XBUFMAX)) == NULL)
				{ error = YES;  break; }
		}
		if (error)
		{
			DEBUG_MSG("area_polygon 領域指定ポリゴン描画用ワーク　確保失敗");
			return -1;
		}
		DEBUG_MSG("area_polygon 領域指定ポリゴン描画用ワーク　確保成功");
	}
	if (px == NULL)
	{
		if ((px = (areapos*)malloc(sizeof(areapos)*MAXP*2)) == NULL)
			return -1;
		py = px + MAXP;
		pnum = 0;
	}
	return 0;
}


static void area_clear()
{
	memset(area_buf, 0, (areaxlen >> 3)*areaylen);
}


static void area_hline(int x1,int x2,int y)
{
	char *p;  int x,leftx,rightx,xr1,xr2;
	if (x1 > x2)
		swap(x1,x2);
	p = area_buf + (areaxlen >> 3) * y + (x1 >> 3);
	leftx = x1 & 0xfff8;
	xr1 = x1 & 7;
	rightx = x2 & 0xfff8;
	xr2 = x2 & 7;
	if (leftx == rightx)
	{
		*p |= (0xff << xr1) & (0xff >> (7-xr2));
	}
	else
	{
		x = leftx;
		*p++ |= (0xff << xr1) & 0xff,  x += 8;	// 左端
		while (x < rightx)						// 真ん中
			*p++ = 0xff,  x += 8;
		*p |= (0xff >> (7-xr2));				// 右端
	}
}



static void area_polygon(areapos *xlist,areapos *ylist)
{
	int i;
	for (i=0; i<areaylen; i++)
		*xbuf[i] = RIGHTMAX;
	int getsign(int n)
	{
		return (n<0 ? -1 : n>0 ? 1 : 0);
	}
	int f1,f2,pnum;
	for (pnum=0; xlist[pnum]>=0; pnum++)	// 頂点の数をかぞえる
		;
	// 始点での頂点の例外処理のために､前の辺の符号をきめる
	f1=0;
	for (i=1; i<pnum; i++) {
		f2=getsign(ylist[i]-ylist[i-1]);
		if (f2!=0)
			f1=f2;
	}
	f2=getsign(ylist[0]-ylist[pnum-1]);
	if (f2!=0)
		f1=f2;
	// x 座標リストの作成
	void makebuf(int x1,int y1,int x2,int y2)
	{
		int xmax,ymax;
		xmax = EIMgetxsize()-1;
		ymax = EIMgetysize()-1;
		void sort_x()		// (x1,y1) をバッファに登録する
		{
			if (x1<0 || xmax<x1 || y1<0 || ymax<y1)
				return;
			int i;
			for (i=0; i<XBUFMAX; i++)
			{
				if (xbuf[y1][i] > x1)
				{
					int j;
					if (i==XBUFMAX-1)
					{
						xbuf[y1][i] = x1;
						return;
					}
					for (j=XBUFMAX-1; j>i; j--)
						xbuf[y1][j] = xbuf[y1][j-1];
					xbuf[y1][i] = x1;
					break;
				}
			}
		}
		int f2;
		f2 = getsign(y2-y1);
		if (f2==0)
			return;
		if (f1*f2==-1)
			sort_x();
		int dx,dy,ux,uy;
		dx = abs(x2-x1);
		dy = abs(y2-y1);
		ux = getsign(x2-x1);
		uy = getsign(y2-y1);
		if (dx >= dy) {
			int r = dx/2;
			for (;;) {
				if (x1==x2) {
					f1=f2;
					break;
				}
				x1 += ux, r += dy;
				if (r >= dx) {
					r -= dx, y1 += uy;
					sort_x();
				}
			}
		} else {
			int r = dy/2;
			for (;;) {
				if (y1==y2) {
					f1=f2;
					break;
				}
				y1 += uy, r += dx;
				if (r >= dy)
					r -= dy, x1 += ux;
				sort_x();
			}
		}
	}
	for (i=0; i<pnum-1; i++)
		makebuf(xlist[i],ylist[i],xlist[i+1],ylist[i+1]);
	makebuf(xlist[pnum-1],ylist[pnum-1],xlist[0],ylist[0]);
	// 領域バッファへの出力
	for (i=0; i<areaylen; i++) {
		int j;
		for (j=0; j<XBUFMAX; j+=2) {
			if (_max(xbuf[i][j],xbuf[i][j+1]) < areaxlen)
				area_hline(xbuf[i][j],xbuf[i][j+1],i);
			else
				break;
		}
	}
}




int area_input(int type)
// type  0=AREA_BOX  1=AREA_POLYGON
// 返値: 0=承認  1=取消
{
	int lat2xlen, lat2ylen;
	DMimage_getlatticesize(&lat2xlen,&lat2ylen);
	area_clear();
	if (type == AREA_BOX)
	{
		int step = 0;
		int x1=0,y1=0,x2,y2;
		void drawcsr(int msx,int msy)
		{
			if (step==1)
			{
				int tx,ty;
				tx = DMimage_getx(msx),  ty = DMimage_gety(msy);
				int p1,p2,p3,p4;
				p1=x1,p2=y1,p3=tx,p4=ty;
				if (p1 > p3)
					swap(p1,p3);
				if (p2 > p4)
					swap(p2,p4);
				if (areaadj)
				{
					p1 = p1 - p1 % lat2xlen;
					p2 = p2 - p2 % lat2ylen;
					p3 = p3 - p3 % lat2xlen + lat2xlen - 1;
					p4 = p4 - p4 % lat2ylen + lat2ylen - 1;
					p3 = _min(p3,areaxlen-1);
					p4 = _min(p4,areaylen-1);
				}
				MOFF; EIMboxline(p1, p2, p3, p4, white, DrawXOR); MON;
			}
		}
		pnum=-1;
		for(;;)
		{
			int prex,prey;
			if (step == 0 || areaadj)
				DMdispcsr(ms.x,ms.y);
			drawcsr((prex=ms.x),(prey=ms.y));
			do
				ms_get(&ms);
			while (ms.dx==0 && ms.dy==0 && ms.btn1==OFF && ms.btn2==OFF &&
				   key_chk()==0);
			if (step == 0 || areaadj)
				DMerasecsr();
			drawcsr(prex,prey);		// 消去
			scrollForCsr(1,1);
			if (ms.btn1==OFFON)
			{
				if (step==0) 			// 始点指定
					step=1, x1=DMimage_getx(ms.x), y1=DMimage_gety(ms.y);
				else if (step==1) 		// 終点指定
				{
					x2=DMimage_getx(ms.x), y2=DMimage_gety(ms.y);
					if (x1 > x2)
						swap(x1,x2);
					if (y1 > y2)
						swap(y1,y2);
					if (areaadj)
					{
						x1 = x1 - x1 % lat2xlen;
						y1 = y1 - y1 % lat2ylen;
						x2 = x2 - x2 % lat2xlen + lat2xlen - 1;
						y2 = y2 - y2 % lat2ylen + lat2ylen - 1;
						x2 = _min(x2,areaxlen-1);
						y2 = _min(y2,areaylen-1);
					}
					int y;
					for (y=y1; y<=y2; y++)
						area_hline(x1,x2,y);
					ax1 = x1, ay1 = y1, ax2 = x2, ay2 = y2;
					return 0;
				}
			}
			if (ms.btn2==OFFON)
			{
				if (step==0)
					return -1;
				else if (step==1)
					step=0;
			}
		}
	}
	else
	{
		bool first;
POLY_RETRY:
		pnum = 0;
		px[0] = py[0] = -1;
		ax1 = ay1 = 0xffff;
		ax2 = ay2 = 0;
		void drawcsr(int msx,int msy)
		{
			int tx,ty;
			tx = DMimage_getx(msx),  ty = DMimage_gety(msy);
			if (pnum > 0)
			{
				int x1,y1;
				x1 = px[pnum-1], y1 = py[pnum-1];
				MOFF; EIMline(x1,y1,tx,ty,white,DrawXOR); MON;
			}
		}
		first = YES;
		for (;;)
		{
			int pre_x,pre_y;
			DMdispcsr(ms.x, ms.y);
			drawcsr(ms.x, ms.y);
			pre_x = ms.x,  pre_y = ms.y;
			do
				ms_get(&ms);
			while (ms.dx == 0 && ms.dy == 0 &&
				   ms.btn1 == OFF && ms.btn2 == OFF &&
				   key_chk() == 0);
			DMerasecsr();
			drawcsr(pre_x, pre_y);	// 消去
			scrollForCsr(1,1);
			if ((ms.btn1 == OFFON || (ms.btn1 == ON && !first)) &&
				ms.btn2 == OFF)
			{
				if (pnum < MAXP-1)
				{
					int tx,ty;

					tx = DMimage_getx(ms.x),  ty = DMimage_gety(ms.y);
					if (pnum == 0 || tx!=px[pnum-1] || ty!=py[pnum-1])
					{
						if (tx < ax1)
							ax1 = tx;
						if (ax2 < tx)
							ax2 = tx;
						if (ty < ay1)
							ay1 = ty;
						if (ay2 < ty)
							ay2 = ty;
						px[pnum] = tx,  py[pnum] = ty;
						if (pnum >= 1)
						{
							int x1,y1,x2,y2;
							x1 = px[pnum-1], y1 = py[pnum-1];
							x2 = px[pnum  ], y2 = py[pnum  ];
							MOFF;
							EIMline(x1,y1,x2,y2,white,DrawXOR);
							EIMpset(x2,y2,white,DrawXOR);
							MON;
						}
						pnum++;
					}
				}
			}
			if (ms.btn1 == OFF || ms.btn1 == ONOFF)
				first = NO;
			if (ms.btn2 == ONOFF)
			{
				// ラバー表示を消す
				int i;
				for (i=1; i<pnum; i++)
				{
					int x1,y1,x2,y2;
					x1 = px[i-1], y1 = py[i-1];
					x2 = px[i  ], y2 = py[i  ];
					MOFF;
					EIMline(x1,y1,x2,y2,white,DrawXOR);
					EIMpset(x2,y2,white,DrawXOR);
					MON;
				}
				if (pnum == 0)
					goto POLY_CANCEL;
				else if (pnum >= 3 && (ms.btn1 == OFF || ms.btn1 == ONOFF))
					goto POLY_ACCEPTED;
				else
					goto POLY_RETRY;
			}
		}
POLY_ACCEPTED:
		px[pnum] = py[pnum] = -1;
		if (pnum >= 3)
			area_polygon(px,py);
		return 0;
POLY_CANCEL:
		return -1;
	}
}


void area_drawbound()
{
	if (pnum == -1)
	{
		MOFF; EIMboxline(ax1,ay1,ax2,ay2,white,DrawXOR); MON;
	}
	else if (pnum >= 3)
	{
		int i;
		for (i=1; i<pnum; i++)
		{
			int x1,y1,x2,y2;
			x1 = px[i-1], y1 = py[i-1];
			x2 = px[i  ], y2 = py[i  ];
			MOFF;
			EIMline(x1,y1,x2,y2,white,DrawXOR);
			EIMpset(x2,y2,white,DrawXOR);
			MON;
		}
		MOFF;
		EIMline(px[pnum-1],py[pnum-1],px[0],py[0],white,DrawXOR);
		EIMpset(px[0],py[0],white,DrawXOR);
		MON;
	}
}


static char bit8[] = {1,2,4,8,16,32,64,128};


bool area_chkxy(int x, int y)	// (x,y) が領域指定されているかを調べる
{
	if (x < 0 || y < 0 || areaxlen <= x || areaylen <= y)
		return NO;
	if (!areasizevar)
	{
		char r = (x & 7);
		return (*(area_buf+y*(AREAXLEN/8)+(x>>3)) & bit8[r]) == 0 ? NO : YES;
	}
	else
	{
		char r = (x & 7);
		return (*(area_buf+y*(areaxlen>>3)+(x>>3)) & bit8[r]) == 0 ? NO : YES;
	}
}


bool area_chkxy2(int x,int y)	// (x,y)-(x+1,y+1)が領域指定されているか
{
	if (x+1 < 0 || y+1 < 0 || areaxlen <= x || areaylen <= y)
		return NO;
	char *p;
	int xsize;
	if (!areasizevar)
		p = area_buf+y*(AREAXLEN/8)+(x>>3), xsize = AREAXLEN;
	else
		p = area_buf+y*(areaxlen>>3)+(x>>3), xsize = areaxlen;
	int r = (x & 7);
	if (0 <= y)
	{
		if (0 <= x)
		{
			if ((*p & bit8[r]) != 0)
				return YES;
		}
		if (x+1 < xsize)
		{
			if (r == 7)
				{ if ((*(p+1) & bit8[0]) != 0)  return YES; }
			else
				{ if ((*p & bit8[r+1]) != 0)  return YES; }
		}
	}
	if (y+1 < areaylen)
	{
		p += (xsize>>3);
		if (0 <= x)
		{
			if ((*p & bit8[r]) != 0)
				return YES;
		}
		if (x+1 < xsize)
		{
			if (r == 7)
				{ if ((*(p+1) & bit8[0]) != 0)  return YES; }
			else
				{ if ((*p & bit8[r+1]) != 0)  return YES; }
		}
	}
	return NO;
}


int area_chkxylen(int x,int xmax,int y,bool nega)
// (x,y) から右に何ドット連続して指定されているかを調べる(or 0)
// nega: 働きを逆にする(領域指定されていない点の連続数を求める)
{
	int _maxx = _min(xmax,areaxlen-1);
	if (x > _maxx)
		return 0;
	int xbytes = areaxlen >> 3;
	char *p = area_buf + y*xbytes + (x>>3);
	int i,r;
	if (!nega)
	{
		for (i=x,r=x&7; i<=_maxx; )
		{
			if (r==0 && *p == 255)
			{
				i+=8, p++;
				continue;
			}
			else if ((*p & bit8[r]) == 0)
				break;
			i++;
			if (++r == 8)
				r=0, p++;
		}
	}
	else
	{
		for (i=x,r=x&7; i<=_maxx; )
		{
			if (r==0 && *p == 0)
			{
				i+=8, p++;
				continue;
			}
			else if ((*p & bit8[r]) != 0)
				break;
			i++;
			if (++r == 8)
				r=0, p++;
		}
	}
	i = _min(_maxx+1, i);
	return i-x;
}


void area_getboundxy(int *x1, int *y1, int *x2, int *y2)
// 領域指定された部分を囲む矩形を取得
{
	*x1 = ax1;
	*y1 = ay1;
	*x2 = ax2;
	*y2 = ay2;
}


/*--------------------------------------------------------*/
/*         INT 23h, 24h の割り込みハンドラの登録          */
/*          High-C 割り込み処理のサンプルより             */
/*--------------------------------------------------------*/

#if 0

	typedef struct {
		int selecter ;	// native vector selecter
		int offset ;	// native vector offset
		int real_vect ;	// real vector
	} vector_t ;

	static vector_t    int23, int24 ;  // 過去のベクタの退避用

	#pragma Calling_convention( C_interrupt ) ; /*  割り込みルーチン開始  */

	static void int23h( Machine_status Stat )
	{
		Stat.Flags = Stat.Flags ;   /*  dummy  */
		return ;                    /*  iret  */
	}

	static void int24h( Machine_status Stat )
	{
		Stat.AX = 3 ;               /*  system call fault  */
		return ;                    /*  iret  */
	}

	#pragma Calling_convention() ;              /*  割り込みルーチン終了  */

	static void dos_extender_call( int interrupt, int param )
	{
		Registers.DS.W = getds() ;
		Registers.AX.W = interrupt ;
		Registers.CX.W = param ;
		calldos() ;
	}

	void ARTsetintvector( void )
	// int 23h/24h の割り込みベクタを int23h()/int24h() に変更
	{
		union {
			_far void (*ptr)() ;
			struct {  unsigned int off ;  unsigned short seg ;  }  reg ;
		} farptr23h, farptr24h ;

		/*  int 23h の退避  */
		dos_extender_call( 0x2502, 0x0023 ) ;
		int23.selecter = Registers.ES.W;
		int23.offset = Registers.BX.R ;

		dos_extender_call( 0x2503, 0x0023 ) ;
		int23.real_vect = Registers.BX.R ;

		farptr23h.ptr = (_far void (*)())int23h ;
		Registers.DS.W = farptr23h.reg.seg ;
		Registers.AX.W = 0x2506 ;
		Registers.CX.W = 0x0023 ;
		Registers.DX.R = farptr23h.reg.off ;
		calldos() ;

		/*  int 24h の退避  */
		dos_extender_call( 0x2502, 0x0024 ) ;
		int24.selecter = Registers.ES.W ;
		int24.offset = Registers.BX.R ;

		dos_extender_call( 0x2503, 0x0024 ) ;
		int24.real_vect = Registers.BX.R ;

		// 割り込みベクタの設定(AX=2506H)
		farptr24h.ptr = (_far void (*)())int24h ;
		Registers.DS.W = farptr24h.reg.seg ;
		Registers.AX.W = 0x2506 ;
		Registers.CX.W = 0x0024 ;
		Registers.DX.R = farptr24h.reg.off ;
		calldos() ;
	}

	void ARTresetintvector( void )
	// int 23h/24h の割り込みベクタを元に戻す
	{
		/*  int 23h の復帰  */
		Registers.AX.W = 0x2507 ;
		Registers.CX.W = 0x0023 ;
		Registers.DS.W = int23.selecter ;
		Registers.DX.R = int23.offset ;
		Registers.BX.R = int23.real_vect ;
		calldos() ;

		/*  int 24h の復帰  */
		Registers.AX.W = 0x2507 ;
		Registers.CX.W = 0x0024 ;
		Registers.DS.W = int24.selecter ;
		Registers.DX.R = int24.offset ;
		Registers.BX.R = int24.real_vect ;
		calldos() ;
	}
#endif

	void ARTsetintvector( void )
	{
		FM_SetVector();
	}
	
	void ARTresetintvector( void )
	{
		FM_ResetVector();
	}

/*--------------------------------------------------------*/
/*                      三角関数処理                      */
/*--------------------------------------------------------*/

#if 0
	deci *atan512_tbl;
#endif

int mathtbl_init(void)
{
#if 0
	if ((atan512_tbl = (deci*)malloc(sizeof(deci)*(DUNIT+1))) == NULL)
	{
		return -1;
	}
	int i;
	for (i=0; i<=DUNIT; i++)
		atan512_tbl[i] = FD(atan((double)i / DUNIT) * 512.0 / (2*_PI));
#endif
	return 0;
}

deci atan512(int theta)
{
#if 0
	if (theta > DUNIT)
		theta = DUNIT;
	else if (theta < 0)
		theta = 0;
	return atan512_tbl[theta];
#else
	return 0;
#endif
}

#if 0

static	int		*__sin, *__cos;


int math32_init(void)
{
	char *p;
	if ((p = malloc(sizeof(int)*
	
}


void math32_end(void)
{
}

#endif


void hline_func(int x1, int x2, int y, void func(int x1, int x2, int y)!)
{
	int ix = x1;
	while (ix <= x2)
	{
		int l1 = mask_chkxylen(ix,x2,y,NO);
		ix += l1;
		if (ix > x2)
			break;
		int l2 = mask_chkxylen(ix,x2,y,YES);
		if (l2 > 0)
			func(ix,ix+l2-1,y);
		ix += l2;
		if (l1 <= 0 && l2 <=0)
			break;
	}
}

/* end of sub.c */
