//
/* --------------------------------------------------------------------------------------------------------
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;
}
}
// 戻る