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