//
/* --------------------------------------------------------------------------------------------------------
manu_cal.java コンピュータのしくみ(手動計算機) ver. 1.00 (JDK 1.02)
ueyama@infonet.co.jp 2009.02.21
-------------------------------------------------------------------------------------------------------- */
import java.applet.*;
import java.awt.*;
public class manu_cal extends Applet implements Runnable
{
// Bus Acc Reg M0 M1 M2 M3
int Sox[]={ 31, 163, 323, 431, 515, 599, 683}; // 「〜を」スイッチ表示 X座標値
int Sby = 28; // 「Iを」スイッチ表示 Y座標値
int Soy = 34; // 「〜を」スイッチ表示 Y座標値
int Sot[]={ 0, 2, 1, 0, 0, 0, 1}; // 表示回路の種類
// Acc Reg M0 M1 M2 M3 Reg
int Six[]={112, 272, 380, 464, 548, 632, 776}; // 「〜に」スイッチ表示 X座標値
int Siy = 218; // 「〜に」スイッチ表示 Y座標値
int Rx[]={ 75, 312, 312, 558, 558, 558, 558, 772}; // レジスタ表示 X座標値
int Ry[]={285, 285, 306, 285, 302, 319, 336, 285}; // レジスタ表示 Y座標値
int Ro[]={ 63, 80, 80, 42, 42, 42, 42, 62}; // レジスタ名表示 X座標オフセット値
int Rv[]={ 0, 0, 0, 0, 0, 0, 0, 0}; // In, Acc, Reg, M0, M1, M2, M3, Out の値
int Bi[]={112, 196, 380, 464, 548, 632, 776}; // 入力信号のバスとの接続位置 (X座標値)
int Bo[]={112, 172, 332, 440, 524, 608, 692, 0}; // 出力信号のバスとの接続位置 (X座標値)
int Adr=0; // Memory Address (0〜3)
int Mr=-1; // 読み出しレジスタ・メモリアドレス
int Mw=-1; // 書き込みレジスタ・メモリアドレス
int Com=-1; // 命令 No.
int Md=0; // 演算モード 0: ADD 1: AND 2: NOT
boolean Dm=false; // 表示モード true: 8bit false: 1bit
boolean Wri=false; // 書き込み実行
boolean Z=true; // 全レジスタ 0 Flag
boolean Cs=false; // true: 演算実行中
boolean Bm=false; // 「〜を」スイッチ ON 時の表示モード
int T=0; // タイマー
int Mx=0; // ドット(マーカー)の表示座標
int Wait=128;
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=910; h=258; ox= 0; oy= 0; break; // 回路図
case 1: w= 52; h= 23; ox= 910; oy= 0; break; // 命令ボタン
case 2: w= 26; h= 23; ox= 910; oy=115; break; // ボタン
case 3: w= 22; h= 19; ox= 841; oy=517; break; // "レ" ボタン (小)
case 4: w= 60; h= 4; ox= 988; oy=272; break; // ドット
case 5: w= 11; h= 11; ox= 988; oy=115; break; // ラジオボタン
case 6: w= 7; h= 10; ox=1010; oy=115; break; // 0,1
case 7: w= 73; h= 11; ox= 910; oy=184; break; // 文字
case 8: w=129; h= 18; ox= 910; oy=283; break; // レジスタ
case 9: w= 86; h= 13; ox= 669; oy=516; break; // 「I を」スイッチ (1bit)
case 10: w= 86; h= 41; ox= 669; oy=529; break; // 「I を」スイッチ (8bit)
case 11: w= 20; h= 98; ox=1006; oy=301; break; // 「〜を」スイッチ (1bit)
case 12: w= 48; h= 98; ox= 910; oy=301; break; // 「〜を」スイッチ (8bit)
case 13: w= 11; h= 19; ox=1066; oy= 0; break; // 「〜に」スイッチ
case 14: w= 24; h= 12; ox=1024; oy=115; break; // 1, 8
case 15: w= 40; h= 30; ox= 988; oy=127; break; // 演算回路
case 16: w= 13; h=101; ox=1028; oy=127; break; // レジスタ入力信号
case 17: w= 13; h= 89; ox=1046; oy=268; break; // 演算回路入力信号
case 18: w= 46; h= 20; ox= 988; oy=228; break; // Acc 入力信号
case 19: w= 26; h= 11; ox=1046; oy=357; break; // Acc 入力信号
case 20: w= 42; h= 13; ox= 841; oy=536; 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);
gx.dispose();
}
public void dsp_bus(int r, int w, int c) // バスの信号表示
{ // r: 読み出しレジスタ No. w: 書き込み 〃
int mx, mn;
Graphics gx=getGraphics();
mn=Math.min(Bi[w],Bo[r]);
mx=Math.max(Bi[w],Bo[r]);
gx.clipRect(mn, 34, mx-mn, 5);
gx.clearRect(mn, 34, mx-mn, 5);
gx.drawImage(Img,112,34-(516+5*c),this);
gx.dispose();
}
public void dsp_reg(int x, int y, int n) // レジスタ値の2進数表示
{
int i,j;
for(i=0,j=128; i<8; i++,j/=2) dsp_g(x+16*i+5, y+4, ((n & j)==0)?0:1, 0, 6);
}
public void dsp_fig() // 回路図の表示
{
int i;
dsp_g(0,0,0,(Dm)?0:1,0); // 回路図の表示
dsp_g(214, 115, 0, Md, 15); // 演算回路の表示
for(i=0; i<3; i++) dsp_g(211, 163+i*15, (Md==i)?1:0, 0, 5); // Radio Button (ADD/AND/NOT)
dsp_g(Sox[0],(Dm)?0:28,(Mr==0)?1:0,0,(Dm)?10:9); // 「Iを」スイッチ の表示
for(i=1; i<7; i++) dsp_g(Sox[i],Soy,(Mr==i)?1:0,Sot[i],(Dm)?12:11); // 「〜を」スイッチ の表示
for(i=0; i<7; i++) dsp_g(Six[i],Siy,0,0,13); // 「〜に」スイッチ の表示
dsp_g(665, 382, 0, 0,14); // "1" の表示
dsp_g(650, 383, (Dm)?0:1, 0, 5); // Radio Button "1" の表示
dsp_g(696, 382, 1, 0,14); // "8" の表示
dsp_g(681, 383, (Dm)?1:0, 0, 5); // Radio Button "8" の表示
}
public void paint(Graphics g) // 画面の表示
{
int i;
g.clearRect(0, 0, size().width, size().height);
dsp_fig(); // 回路図の表示
dsp_g(463, Ry[3]+3, 0, 8, 7); // "メモリ" の表示
for(i=0; i<8; i++) dsp_g(Rx[i]-Ro[i], Ry[i]+3, 0, i, 7); // レジスタ名の表示
for(i=0; i<8; i++) dsp_g(Rx[i], Ry[i], 0, 0, 8); // レジスタの表示
for(i=0; i<8; i++) dsp_reg(Rx[i],Ry[i],Rv[i]); // レジスタ値の2進数表示
for(i=0; i<4; i++) dsp_g(501, Ry[i+3]+3, (Adr==i)?1:0, 0, 5); // Radio Button (address) の表示
for(i=0; i<5; i++) dsp_g(196+60*i,376,(Cs && i<4)?2:0,i,1); // 命令ボタン の表示
dsp_g(182,308,(Rv[0]==0)?2:0,0, 3); // "レ" ボタン(小) の表示
dsp_g(506,376,(Wait==1024)?2:0,2,2); // "<<" ボタン の表示
dsp_g(536,376,(Wait==16)?2:0,1,2); // ">>" ボタン の表示
dsp_g(506+Mx*8,370,0,0, 4); // ドットの表示
dsp_g(596,376,(Z)?2:0,0,2); // "レ" ボタン の表示
dsp_g(760,382,0,(Bm)?1:0,20); // チェックボックス の表示
}
public void run()
{
int a, i;
while(true)
{
try
{
th.sleep(Wait);
}
catch (InterruptedException e){}
T++;
if(T==4)
{
reg_write(Mr, Mw);
dsp_reg(Rx[Mw+1],Ry[Mw+1],Rv[Mw+1]); // レジスタ値の2進数表示
if(Com==4 && Wri) Cs=!Cs; // 演算処理の状態を切り替える
}
}
}
public void stop()
{
if(th!=null)
{
th.stop();
th=null;
}
}
public int bin_ed(int n, int m) // レジスタ値の更新
{
int p=(int)Math.pow(2,m); // p = 2 ^ m
if((n & p) ==0) n+=p; // 値の更新
else n-=p;
return n;
}
public void dsp_sw(int r) // 「〜を」スイッチ の表示
{
if(r==0) dsp_g(Sox[0],(Dm)?0:28,1,0,(Dm)?10:9); // 「Iを」スイッチ の表示
else dsp_g(Sox[r],Soy,1,Sot[r],(Dm)?12:11); // 「〜を」スイッチ の表示
}
public void reg_write(int r, int w) // 入力信号とレジスタ値の表示
{ // r: 読み出しレジスタ No. w: 書き込み 〃
int i;
if(w>=0)
{
dsp_g(Six[w],Siy,1,0,13); // 「〜に」スイッチ の表示
if(r>=0)
{
if(w==1) // 演算
{
switch(Md) // Md 0: ADD 1: AND 2: NOT
{
case 0: Rv[2]=Rv[1] + Rv[r]; break; // ADD
case 1: Rv[2]=Rv[1] & Rv[r]; break; // AND
case 2: Rv[2]=255-Rv[r]; break; // NOT
}
dsp_g(196,Siy-184,(Dm)?3:1,0,17); // 演算回路入力信号の表示
if(Md<2) dsp_g(163,127,1,(Dm)?1:0,18); // アキュムレータからの入力信号の表示
dsp_g(259,124,1,(Dm)?1:0,19); // 演算回路出力信号の表示
}
else
{
Rv[w+1]=Rv[r]; // Rv[]: In,Acc,Reg,M0,M1,M2,M3,Out の値
dsp_g(Six[w],Siy-184,(Dm)?3:1,0,16); // レジスタ入力信号の表示
}
dsp_bus(r,w,1); // バスの信号(赤色)表示
dsp_reg(Rx[w+1],Ry[w+1],Rv[w+1]); // レジスタ値の2進数表示
Wri=true;
}
}
}
public boolean mouseDown(Event e, int mx, int my) // マウスがクリックされたときの処理
{
int a, i, l, m=0, n=0;
if(my<95) // 「〜を」スイッチをクリック
{
if(mx<105 && inside(my,21,46)) Mr=0;
for(i=1;i<7;i++) if(inside(mx,Sox[i]-10,Sox[i]+29) && my>60) Mr=i;
if(Mr>=0)
{
dsp_sw(Mr); // 「〜を」スイッチ の表示
if(Bm) // 全レジスタの入力信号表示
{
dsp_g(196,Siy-184,1,0,17); // 演算回路入力信号の表示
for(i=0;i<7; i++) if(i!=1) dsp_g(Six[i],Siy-184,1,0,16); // レジスタ入力信号の表示
dsp_bus(0,6,1); // バスの信号(赤色)表示
}
}
}
if(inside(my,209,244) && Mr>=0) // 「〜を」スイッチが ON であれば…
{
for(i=0;i<7;i++) if(inside(mx,Six[i]-10,Six[i]+29)) Mw=i; // 「〜に」スイッチをクリック
if(Mw>=0)
{
if(Bm) // 全レジスタの入力信号表示
{
dsp_g(196,Siy-184,0,0,17); // 演算回路入力信号の表示
for(i=0;i<7; i++) if(i!=1) dsp_g(Six[i],Siy-184,0,0,16); // レジスタ入力信号の表示
dsp_bus(0,6,0); // バスの信号(赤色)表示
}
reg_write(Mr, Mw); // 入力信号とレジスタ値の表示
}
}
if(inside(my,116,165)) // レジスタ、メモリをクリック ?
{
if(Mr<0)
{
for(i=0; i<6; i++) if(inside(mx,Six[i]+13,Six[i]+50)) Mr=i+1;
if(Mr>=0) dsp_sw(Mr); // 「〜を」スイッチ の表示
}
else if(Mw<0)
{
for(i=0; i<7; i++) if(inside(mx,Six[i]+13,Six[i]+50)) Mw=i;
if(Mw>=0) reg_write(Mr, Mw); // 入力信号とレジスタ値の表示
}
}
if(inside(mx,208,258) && inside(my,161,201)) // 演算モードの変更
{
Md=(my-161)/15; // 演算モード
dsp_g(214, 115, 0, Md, 15); // 演算回路の表示
for(i=0; i<3; i++) dsp_g(211,163+i*15,(Md==i)?1:0,0,5); // Radio Button (ADD/AND/NOT) の表示
}
if(inside(my,285,353)) // レジスタテーブルをクリック ?
{
if(inside(mx,492,552)) // Radio Button をクリック
{
Adr=(my-285)/18; // アドレス
for(i=0;i<4;i++) dsp_g(501,Ry[i+3]+3,(Adr==i)?1:0,0,5); // Radio Button (address) の表示
}
else // レジスタテーブルをクリック
{
for(i=0; i<8; i++)
{
if(inside(mx,Rx[i],Rx[i]+129) && inside(my,Ry[i]+1,Ry[i]+16))
{
m=7-(mx-Rx[i])/16;
Rv[i]=bin_ed(Rv[i], m); // レジスタの値を更新
dsp_reg(Rx[i],Ry[i],Rv[i]); // レジスタ値の2進数表示
if(i==0) dsp_g(182,308,(Rv[0]==0)?2:0,0, 3); // "レ" ボタン(小) の表示
}
if(Rv[i]>0)
{
Z=false;
dsp_g(596,376,0,0,2); // "レ" ボタン有効の表示
}
}
}
if(inside(mx,182,204) && inside(my,308,327) && Rv[0]>0) // "レ" ボタン(小) をクリック
{
Rv[0]=0;
dsp_reg(Rx[0],Ry[0],Rv[0]); // レジスタ値の2進数表示
dsp_g(182,308,1,0,3); // "レ" ボタン(小) の表示
}
}
if(my>376) // ボタン等をクリック ?
{
if(inside(mx,196,488) && (mx-196)%60<52) // 命令ボタンをクリック
{
Com=(mx-196)/60;
if((Com<4 && !Cs) || Com==4)
{
dsp_g(196+60*Com,376,1,Com,1); // 命令ボタン の表示
switch(Com) // 命令の処理
{
case 0: Mr=0; Mw=0; break; // IN
case 1: Mr=1; Mw=6; break; // OUT
case 2: Mr=Adr+3; Mw=0; break; // READ
case 3: Mr=1; Mw=Adr+2; break; // WRITE
case 4: Mr=(Cs)?2:Adr+3; Mw=(Cs)?0:1; break; // CALC 2step 実行の処理も行う
}
dsp_sw(Mr); // 「〜を」スイッチ の表示
T=0;
Wri=true;
}
}
if(inside(mx,506,562)) // "<<" or ">>" ボタン
{
if(inside(mx,506,532) && Wait<1024) // "<<" ボタン
{
Wait*=2; Mx--;
dsp_g(506,376,1,2,2); // "<<" ボタン の表示
}
if(inside(mx,536,562) && Wait>16) // ">>" ボタン
{
Wait/=2; Mx++;
dsp_g(536,376,1,1,2); // "<<" ボタン の表示
}
dsp_g(506+Mx*8,370,0,0,4); // ドットの表示
}
if(inside(mx,596,622) && !Z) // "レ" ボタン
{
dsp_g(596,376,1,0,2); // "レ" ボタン の表示
for(i=0; i<8; i++) Rv[i]=0; // レジスタ値のクリア
for(i=0; i<8; i++) dsp_reg(Rx[i],Ry[i],Rv[i]); // レジスタ値の2進数表示
Z=true;
}
if(inside(mx,638,722)) // 表示モード (1,8bit) の変更
{
Dm=((mx-638)/42==0)?false:true; // 表示モード
dsp_fig(); // 回路図の書き換え
}
if(inside(mx,760,802)) // 表示モード の変更
{
Bm=(Bm)?false:true;
dsp_g(760,382,0,(Bm)?1:0,20); // チェックボックス の表示
}
}
return true;
}
public boolean mouseUp(Event e, int mx, int my) // マウスがクリックされたときの処理
{
int i,m;
if(inside(mx,182,204) && inside(my,308,327)) dsp_g(182,308,2,0,3); // "レ" ボタン(小) をクリック
if(my>376) // ボタン等をクリック ?
{
if(inside(mx,196,488)) // 命令ボタン
{
m=(mx-196)/60;
for(i=0; i<5; i++) dsp_g(196+60*i,376,(Cs && i<4)?2:0,i,1); // 命令ボタン の表示
}
if(inside(mx,506,532)); // "<<" ボタン
{
dsp_g(506,376,(Wait==1024)?2:0,2,2); // "<<" ボタン の表示
dsp_g(536,376,(Wait==16)?2:0,1,2); // ">>" ボタン の表示
}
if(inside(mx,536,562)); // ">>" ボタン
{
dsp_g(506,376,(Wait==1024)?2:0,2,2); // "<<" ボタン の表示
dsp_g(536,376,(Wait==16)?2:0,1,2); // ">>" ボタン の表示
}
if(inside(mx,596,622))
{
dsp_g(596,376,2,0,2); // "レ" ボタン の表示
dsp_g(182,308,2,0,3); // "レ" ボタン(小) の表示
}
}
if(Wri)
{
if(Mr==0) dsp_g(Sox[0],(Dm)?0:28,0,0,(Dm)?10:9); // 「Iを」スイッチを元に戻す
else dsp_g(Sox[Mr],Soy,0,Sot[Mr],(Dm)?12:11); // 「〜を」スイッチを元に戻す
dsp_g(Six[Mw],Siy,0,0,13); // 「〜に」スイッチを元に戻す
if(Mw==1)
{
dsp_g(196,Siy-184,(Dm)?2:0,0,17); // レジスタ入力信号の表示
dsp_g(163,127,0,(Dm)?1:0,18); // レジスタ入力信号の表示
dsp_g(259,124,0,(Dm)?1:0,19); // レジスタ入力信号の表示
}
else dsp_g(Six[Mw],Siy-184,(Dm)?2:0,0,16); // レジスタ入力信号を元に戻す
dsp_bus(Mr, Mw, (Dm)?2:0); // バスの信号を元に戻す
Wri=false;
Mr=-1;
Mw=-1;
}
return true;
}
}
//戻る