//
/* --------------------------------------------------------------------------------------------------------
	schematic.java	コンピュータのしくみ(仮想コンピュータ図解)		ver. 1.00 (JDK 1.02)
																		ueyama@infonet.co.jp 2008.09.01
-------------------------------------------------------------------------------------------------------- */
import java.applet.*;
import java.awt.*;

public class schematic extends Applet implements Runnable
{
				//    Bus Aci Aco Op1 Op2 Reg M0i M0o M1i M1o M2i M2o M3i M3o Out
	int			Sx[]={ 74,121,177,177,188,238,270,326,357,413,444,500,531,587,696};	// スイッチ表示 X座標値
	int			Sy[]={ 26, 61, 76,127,130,192,102,117,125,140,148,163,171,186,215};	//              Y座標値
	int			Ax[]={ 53,121,159,168,182,220,270,308,357,395,444,482,531,569,696};	// 矢印表示 X座標
	int			Ay[]={ 39,109,118,165,225,234,150,159,173,182,196,205,219,228,263};	// 矢印表示 X座標
	int			Aw[]={  1,  0,  2,  3,  0,  2,  0,  2,  0,  2,  0,  2,  0,  2,  0};	// 表示矢印の種類
	int			Ry[]={  6, 27, 48, 69, 86,103,120,142};					// レジスタテーブル表示 Y座標値
	int			Rv[]={  0,  0,  0,  0,  0,  0,  0,  0};					// In, Acc, Reg, M0, M1, M2, M3, Out の値
	int			Bx[]={ 39,  0,250,  0,  0,  0,  0,783};					// In, Reg, Out の図中2進数表示 X座標値
	int			By[]={ 33,  0,258,  0,  0,  0,  0,293};					//                              Y座標値
	int			Isw[][]={{ 0, 1},										// IN     命令で ON にするスイッチ No.
						 { 2,14},										// OUT
						 { 1,16},										// READ
						 { 2,16},										// WRITE
						 { 3, 4, 16, 1, 5},								// ADD
						 { 3, 4, 16, 1, 5}};							// AND
	int			Ix[][]={{38,38,110,110},{249,249,321,321},{782,782,854,854}};	// 入力ポート部多角形 X座標値
	int			Iy[][]={{32,46, 22,  8},{257,271,247,233},{292,306,282,269}};	//                    Y座標値
	Polygon		Inp = new Polygon(Ix[0], Iy[0], 4);							// 入力ポート部多角形
	Polygon		Reg = new Polygon(Ix[1], Iy[1], 4);							// 入力ポート部多角形
	Polygon		Out = new Polygon(Ix[2], Iy[2], 4);							// 入力ポート部多角形
	int			Com=0;													// 命令 No.
	int			Adr=0;													// Memory Address (0〜3)
	int			Ss=-1;													// Second step (for Ss=4; ADD, Ss=5; AND)
	boolean		Z=true;													// 全レジスタ 0 Flag
	int			T=0;
	boolean		Se=false;
	Thread		th=null;
	Image		Img;
	
	public void init()													// 初期設定
	{
		String bg=getParameter("bgcolor");
		int bgc=Integer.valueOf(bg,16).intValue();
		setBackground(new Color(bgc)); 
		MediaTracker mt=new MediaTracker(this);
		Img=getImage(getCodeBase(), getParameter("figure"));
		mt.addImage(Img, 0);
		try
		{
			mt.waitForID(0);
		}
		catch(InterruptedException e){};
	}

	public void start()
	{
		if(th==null)
		{
			th=new Thread(this);
			th.start();
		}
	}
	
	public boolean inside(int x, int a, int b)							// マウスの位置座標チェック
	{
		return (x<=Math.max(a,b) && x>=Math.min(a,b)) ? true:false;
	}

	public void dsp_g(int x, int y, int m, int n, int c)				// 画像の表示
	{
		int			w=0, h=0, ox=0, oy=0;
		Graphics	gx=getGraphics();
		switch(c)
		{
			case  0: w= 86; h= 31; ox=449; oy=320; break;				// スイッチ(バス)
			case  1: w= 72; h= 38; ox=376; oy=320; break;				// スイッチ(レジスタ)
			case  2: w= 28; h= 22; ox=264; oy=320; break;				// 矢印(入力)
			case  3: w= 52; h= 23; ox=613; oy=320; break;				// 命令ボタン
			case  4: w= 26; h= 23; ox=535; oy=320; break;				// クリアボタン
			case  5: w=191; h= 11; ox=  0; oy=320; break;				// Address:
			case  6: w=  4; h=  4; ox=769; oy=320; break;				// Radio Button
			case  7: w=  8; h= 10; ox=773; oy=320; break;				// 0,1
			case  8: w=  7; h= 10; ox=781; oy=320; break;				// 0,1
			case  9: w= 24; h= 32; ox=192; oy=320; break;				// 演算回路記号
		}
		gx.clipRect(x, y, w, h);
		gx.clearRect(x, y, w, h);
		gx.drawImage(Img,x-(ox+m*w),y-(oy+n*h),this);
		if(c<3) gx.drawImage(Img,0,0-320,this);							// 背景の再描画
		gx.dispose();
	}
	
	public void dsp_reg(int x, int y, int w, int h, int n, int c)		// レジスタ値の2進数表示
	{
		int i,j;
		for(i=0,j=128; i<8; i++,j/=2) dsp_g(x+w*i, y+h*i, 0,((n & j)==0)?0:1, c);
	}

	public void paint(Graphics g)										// 画面の表示
	{
		int i,j,k;
		g.clearRect(0, 0, size().width, size().height);
		Graphics gx=getGraphics();
		gx.clipRect(0, 0, size().width, 320);
		gx.drawImage(Img,0,0,this);
		gx.dispose();
		for(i=0; i<15; i++) dsp_g(Sx[i],Sy[i],0,0,(i==0)?0:1);			// スイッチ の表示
		for(i=0; i<6; i++) dsp_g(120+60*i,337,(Ss<0 || i==Ss)?0:2,i,3);	// 命令ボタン の表示
		dsp_g(490,343,0,0,5);											// 「Address」の表示
		for(i=0; i<4; i++) dsp_g(555+36*i,347,0,(i==Adr)?1:0,6);		// Addres ラジオボタンの表示
		dsp_g(715,337,(Z)?2:0,0,4);										// クリアボタンの表示
		for(i=0; i<8; i++) dsp_reg(733,Ry[i],16,0,Rv[i],8);				// レジスタ値の2進数表示
		dsp_reg(Bx[0],By[0],9,-3,Rv[0],7);								// 図中2進数表示 入力ポート
		dsp_reg(Bx[2],By[2],9,-3,Rv[2],7);								//                レジスタ
		dsp_reg(Bx[7],By[7],9,-3,Rv[7],7);								//                出力ポート
		dsp_g(172,181,(Com>3)?Com-3:0,0,9);								// 演算回路記号
	}

	public void run()
	{
		int a, i;
		while(true)
		{
			try
			{
				th.sleep(50);
			}
			catch (InterruptedException e){}
			T++;
			if(T>5 && Com>=0 && Se)										// 命令ボタンをクリック
			{
				for(i=0; i14) a=6+Adr*2+((Com==3)?0:1);
		return a;
	}

	public boolean mouseDown(Event e, int x, int y)						// マウスがクリックされたときの処理
	{
		int a, i, l, m, n;
		Com=-1;
		if(Inp.inside(x,y) || Reg.inside(x,y) || Out.inside(x,y))		// 図中レジスタの2進数をクリック
		{
			n=(x-53)/100;												// レジスタ配列の index (偶然、こうなった)
			l=(int)Math.sqrt(x-12)/10;									// 多角形配列の index   (       同上     )
			m=7-(x-Ix[l][0])/9;											// クリックされた2進数桁数
			Rv[n]=bin_ed(Rv[n], m);										// レジスタ値の更新
			dsp_reg(Bx[n],By[n],9,-3,Rv[n],7);							// レジスタ値の2進数表示
			dsp_reg(733,Ry[n],16,0,Rv[n],8);
		}
		if(inside(x,728,856) && y<154)									// レジスタテーブルをクリック
		{
			for(i=0; i<8; i++)
			{
				if(inside(y,Ry[i]-4,Ry[i]+13))
				{
					m=7-(x-728)/16; 
					Rv[i]=bin_ed(Rv[i], m);								// レジスタ値の更新
					if(i==0 || i==2 || i==7) dsp_reg(Bx[i],By[i],9,-3,Rv[i],7);
					dsp_reg(733,Ry[i],16,0,Rv[i],8);					// レジスタ値の2進数表示
				}
			}
		}
		if(y>337)
		{
			m=x-120;
			if(inside(m,0,352) && m%60<52)								// 命令ボタンをクリック
			{
				if((Ss==m/60) || Ss<0) Com=m/60;
				else Com=-1;
				if(Com>=0)
				{
					dsp_g(120+60*Com, 337, 1,Com,3);					// 命令ボタンの再表示
					dsp_g(172,181,(Com>3)?Com-3:0,0,9);					// 演算回路記号の表示
					for(i=((Ss>0)?3:0); i<((Com>3 && Ss<0)?3:Isw[Com].length); i++)
					{
						a=adr_dec(i);
						dsp_g(Sx[a],Sy[a],0,1,(a==0)?0:1);				// スイッチの表示 (ON)
						dsp_g(Ax[a],Ay[a],Aw[a],1,2);					// 矢印の表示
					}
					if(Com==0) dsp_reg(Bx[0],By[0],9,-3,Rv[0],7);		// 入力ポート値表示の乱れを修正
					switch(Com)											// 命令の処理
					{
						case 0: Rv[1]=Rv[0];		break;				// IN
						case 1: Rv[7]=Rv[1];		break;				// OUT
						case 2: Rv[1]=Rv[Adr+3];	break;				// READ
						case 3: Rv[Adr+3]=Rv[1];	break;				// WRITE
						case 4: if(Ss<0) Rv[2]=Rv[1]+Rv[Adr+3];
								else Rv[1]=Rv[2];	break;				// ADD
						case 5: if(Ss<0) Rv[2]=Rv[1]&Rv[Adr+3];
								else Rv[1]=Rv[2];	break;				// AND
					}
				}
			}
			if(inside(x,545,694))										// Address ボタンをクリック
			{
				Adr=(x-545)/36;
				for(i=0;i<4;i++) dsp_g(555+36*i,347,0,(i==Adr)?1:0,6);	// Address ラジオボタンの表示
			}
			if(inside(x,715,741) && !Z)									// クリアボタンをクリック
			{
				dsp_g(715,337,1,0,4);									// クリアボタンの表示
				for(i=0; i<8; i++) Rv[i]=0;
			}
		}
		Z=(Rv[0]+Rv[1]+Rv[2]+Rv[3]+Rv[4]+Rv[5]+Rv[6]+Rv[7]==0)?true:false;
		return true;
	}

	public boolean mouseUp(Event e, int x, int y)						// マウスボタンが離されたときの処理
	{
		int i;
		if(Com>=0)														// 命令ボタンをクリック
		{
			if(Com>3 && Ss<0) Ss=Com;
			else Ss=-1;
			for(i=0; i<6; i++) dsp_g(120+60*i, 337, (Ss<0 || i==Ss)?0:2, i,3);	// 命令ボタン の表示
			Se=true;
			T=0;
		}
		if(Com>=0 || (inside(x,715,741) && Z))							// 命令ボタン or クリアボタンをクリック
		{
			for(i=0; i<8; i++)
			{
				if(i==0 || i==2 || i==7) dsp_reg(Bx[i],By[i],9,-3,Rv[i],7);	// レジスタの2進数表示
				dsp_reg(733,Ry[i],16,0,Rv[i],8);						// レジスタテーブルの表示
			}
		}
		dsp_g(715,337,(Z)?2:0,0,4);										// クリアボタンの表示
		return true;
	}
}
//
戻る