diff --git a/Makefile.tcpp10 b/Makefile.tcpp10 new file mode 100644 index 0000000..c7e6d7d --- /dev/null +++ b/Makefile.tcpp10 @@ -0,0 +1,32 @@ +# Makefile for Wonbe 0.04j4 +# with GNUmake and gcc / Turbo C++ 1.0 +# Hirotaka JOE Ohkubo 2000/12/04 + +INCLUDE = C:/WWitch/include +C0WW = C:\\WWitch\\lib\\c0wwjpn1.obj +LIBS = C:\\WWitch\\lib\\libww.lib C:\\WWitch\\lsic86ww\\lib\\s\\runtime.lib + +COPTS = -1 -j1 -d -O -Z -ms! -zPCGROUP -zSDGROUP -zGDGROUP +CFLAGS = -DWW + +all: wonbe.fx wonbe32.exe + +wonbe.fx: wonbe.bin + mkfent wonbe.cf + +wonbe.bin: wonbe.obj + tlink /m /c $(C0WW) wonbe.obj, wonbe, wonbe, $(LIBS) + exe2fbin wonbe.exe wonbe.bin + rm wonbe.exe + +wonbe.obj: wonbe.c keywords.h + tcc -I$(INCLUDE) $(COPTS) $(CFLAGS) -c wonbe.c + +wonbe32.exe: wonbe.o win32text.o + gcc -o wonbe32.exe wonbe.o win32text.o -lgdi32 + +wonbe.o: wonbe.c keywords.h + gcc -c -DWIN32 -DCYGWIN wonbe.c + +win32text.o: win32text.c win32text.h + diff --git a/ctb.wb b/ctb.wb new file mode 100644 index 0000000..564fd45 --- /dev/null +++ b/ctb.wb @@ -0,0 +1,290 @@ +10 goto 10000 + +1000 ' 駒表示 +1001 ' X,Y : センター座標, A : 駒データ位置, B : 0x20 で消去, 0x81A1 で '■' +1002 y = Y : if y >= 0 then locate X,y : print chr(B); +1003 for i=A to A+4 step 2 +1004 y = Y + @(i+1) : if y >= 0 then locate X + @(i),y : print chr(B); +1005 next +1006 return + +1100 ' 移動できるかチェック +1101 ' U,V : センター座標, W : 駒データ位置, F : 0 OK / 1 NG +1110 F = 1 : @(P) = 1 'ぶず +1111 if @(1+U+V*12) then goto 1116 +1112 if @(1+U+@(W )+(V+@(W+1))*12) then goto 1116 +1113 if @(1+U+@(W+2)+(V+@(W+3))*12) then goto 1116 +1114 if @(1+U+@(W+4)+(V+@(W+5))*12) then goto 1116 +1115 F = 0 +1116 @(P)=0 : return + +1200 ' スコア表示 +1210 locate 21,11 +1220 if S < 10000 then print " "; +1230 if S < 1000 then print " "; +1240 if S < 100 then print " "; +1250 if S < 10 then print " "; +1260 print S; +1270 return + +1300 ' ブズ回転 +1310 O = rnd(4)+0x81A8 : locate Q+8,R-4 : print chr(O); +1320 T = tick + 66 +1330 return + +1400 ' データと画面をスクロールダウン +1401 ' Y : 消えるライン xy座標系 +1410 for i=Y*12+10 to 13 step -1 : @(i)=@(i-12) : next +1420 for i=1 to 10 : @(i)=0 : next +1430 for i=Y to 4 step -1 : for j=1 to 10 +1440 locate j+8,i-4 : k=@(i*12+j) +1450 if k=1 then print "■"; : goto 1460 +1451 if k=2 then print chr(2); : goto 1460 +1452 print " "; +1460 next : next +1470 return + +3000 ' メインループ +3010 if T < tick then gosub 1300 ' ブズ回転 +3020 if t < tick then goto 3500 ' 落とす + +3100 ' キースキャン +3110 U = x : V = y : W = a +3120 k = scan : if k and l then goto 3150 ' 一度手を離せ。 +3130 if k and scan_a then W = @(W+6) : l = scan_a : goto 3200 +3131 if k and scan_x2 then U = U + 1 : l = scan_x2 : goto 3200 +3132 if k and scan_x3 then V = V + 1 : l = scan_x3 : goto 3200 +3133 if k and scan_x4 then U = U - 1 : l = scan_x4 : goto 3200 +3140 l = 0 ' 何も押されていない +3150 waitvb 1 +3160 goto 3000 + +3200 ' キーによる駒移動 +3210 gosub 1100 ' 移動できるかチェック +3220 if F then if l = scan_x3 then goto 3600 ' 押し込み +3230 if F then goto 3000 ' 動かせない。おしまい。 +3240 ' 動かせる。実行。 +3250 if l = scan_x3 then l = 0 ' : t = tick + w ' 下向きだけはリピート可能 +3260 X = x+9 : Y = y-4 : A = a : B = 32 : gosub 1000 ' 今のを消す +3270 x = U : y = V : a = W +3280 X = x+9 : Y = y-4 : A = a : B = 0x81A1 : gosub 1000 ' 移動後を表示 +3290 goto 3000 +3299 ' メインループ終わり + +3500 ' 時間切れ。一つ下がる +3510 U = x : V = y + 1 : W = a : gosub 1100 +3520 if F then goto 3600 ' 下がれない。 +3530 X = x+9 : Y = y-4 : A = a : B = 32 : gosub 1000 ' 今のを消す +3540 y = V : Y = y-4 : B = 0x81A1 : gosub 1000 ' 移動後を表示 +3550 t = tick + w +3560 play "o1a16" ' 落下音 +3570 goto 3000 + +3600 ' 着底 +3610 ' 埋まったラインを消す +3615 play "o1g8" +3620 @(P)=1 +3621 @(1+x+y*12)=1 +3622 @(1+x+@(a )+(y+@(a+1))*12)=1 +3623 @(1+x+@(a+2)+(y+@(a+3))*12)=1 +3624 @(1+x+@(a+4)+(y+@(a+5))*12)=1 +3630 for i=y+@(a+1) to y+@(a+5) +3640 f=0 : @(P)=1 +3650 for j=1+i*12 to 10+i*12 +3660 if @(j)=0 then f=1 +3670 next +3680 @(P)=0 +3690 if f then goto 3920 ' このラインは消せない。次。 +3710 if i <> R then goto 3780 +3720 ' ブズ抹消! +3730 locate Q+8,R-4 : print chr(2); +3740 S=S+50 : gosub 1200 : play "o4e8~c0" +3760 P=1 : R=22 ' ブズ死亡状態 +3770 goto 3800 +3780 ' ラインだけ消去 +3790 S=S+1 : gosub 1200 : play "g16" +3800 ' データと画面をスクロールダウン +3810 Y=i : gosub 1400 +3870 ' ブズ復元 +3880 if P=1 then goto 3920 +3890 ' ブズが落ちてきたブロックに殴られたか? +3900 if @(P) then P=P+12 : R=R+1 : S=S+75 : gosub 1200 : play "g16c16" +3910 locate Q+8,R-4 : print chr(O); +3920 next ' MAX4ブロック分ループ終了。 + +4000 ' ブズの移動フェーズ +4010 if P=1 then goto 4300 +4020 locate Q+8,R-4 : print " "; : c = 4 +4030 goto 4040 + (O and 1) * 4 + (O and 2) '時計回りの苦肉の策 +4040 if @(P+1)=0 then P=P+1 : Q=Q+1 : goto 4050 ' 0x81A8 右 00 +4041 c=c-1 : if c=0 then goto 4080 +4042 if @(P-12)=0 and R>1 then P=P-12 : R=R-1 : goto 4050 ' 0x81AA 上 10 +4043 c=c-1 : if c=0 then goto 4080 +4044 if @(P-1)=0 then P=P-1 : Q=Q-1 : goto 4050 ' 0x81A9 左 01 +4045 c=c-1 : if c=0 then goto 4080 +4046 if @(P+12)=0 then P=P+12 : R=R+1 : goto 4050 ' 0x81AB 下 11 +4047 c=c-1 : if c=0 then goto 4080 +4048 goto 4040 +4050 ' 動けた! 「ぷふぁ」 +4051 ' ぶずが画面上に抜けたらゲームオーバー +4052 if R < 4 then locate Q+8,R-3 : print chr(1);: goto 4400 +4060 gosub 1300 +4070 goto 4300 +4080 ' ぶずは囲まれた! 「ぎゃう」 +4090 S = S + 100 : gosub 1200 : play "e8~>c0" ': play "o6#0c8#1e8#2g8" +4100 locate Q+8,R-4 : print chr(2); +4110 @(P) = 2 : P=1 : Y=R : R=22 +4120 ' この死体でこのラインが埋まるか? +4130 f=0 +4140 for i=Y*12+1 to Y*12+10 +4150 if @(i)=0 then f=1 +4160 next +4170 if f then goto 4300 +4180 waitvb 7 : play "g16" : gosub 1400 +4190 S=S+1 : gosub 1200 + +4300 ' 絶対不可侵領域を塗りつぶしてないか→ゲームオーバー +4310 f=1 +4320 for i=1+3*12 to 10+3*12 +4330 if @(i) then f=0 +4340 next +4350 if f then goto 5000 ' 詰まってはいない。 +4400 ' GAME OVER +4410 play "o3edc" +4420 locate 10, 9 : print "G A M E"; +4430 locate 10,11 : print "O V E R"; +4440 k=wait +4450 if scan then goto 4450 ' 手を離せ。 +4455 for i=0 to 17: locate 9,i : print " ";:next +4460 goto 10050 ' スタート画面へ。 + +5000 ' ブズ生成 *スタート時突入ポイント* +5010 if P<>1 then goto 5100 +5020 Q=rnd(10)+1 +5030 R=16+rnd(7)-rnd(7) : if R = 22 then R=20 +5040 P=Q+R*12 : if @(P) then goto 5020 +5050 gosub 1300 + +5100 ' 次の駒生成 +5110 for j=4 to 7: locate 22,j : print " "; : next +5120 a = b : b = rnd(19)*7+K +5130 X = 24 : Y = 6 : B = 0x8E9F : A = b : gosub 1000 +5140 x = 5 : y = 2 ' 駒の初期位置 +5150 t = tick + w ' 次のタイムアウト +5160 l = scan_x3 ' 下が続けて入ってしまうのを避けるため +5170 goto 3000 + +9999 end + +10000 ' いろいろ準備ちゅう... +10010 randomize tick +10020 gosub 20000 ' 表示初期化 +10030 play "cego6c2rco5gec2" ' テーマ音楽、でもない。 +10040 gosub 30000 '駒データ準備 +10049 ' ここから再開 +10050 locate 10, 9 : print "P U S H"; +10051 locate 10,11 : print " K E Y "; +10060 k = wait +10070 play "#0c#1e#2g" +10080 for i=0 to 17: locate 9,i : print " ";:next + +11000 ' ゲーム準備 +11010 b = rnd(19)*7+K ' 最初に落とす駒を準備 +11020 w = 90 +11030 for i=0 to K-1: @(i) = 0 : next +11040 for i=0 to K-1 step 12 : @(i) = 1 : @(i+11) = 1 : next ' ばんぺいくん +11050 for i=12*22+1 to K-1 : @(i) = 1 : next ' これもばんぺいくん(昇圧回路不要) +11060 l = 0 +11070 P = 1 ' ぶず +11080 S = 0 : gosub 1200 ' score +11090 goto 5000 ' メインループ + +20000 ' 画面初期化 +20010 cls +20020 for i=0 to 17: locate 8,i: print "左";: locate 19,i:print "右";: next +20030 locate 2,3 : print "きゃっち"; +20040 locate 4,4 : print "ざ"; +20050 locate 2,5 : print "Buzz"; +20060 locate 2,7 : print "by"; +20070 locate 2,8 : print "流れ星の"; +20080 locate 3,9 : print "ジョヲ"; +20090 locate 22,2 : print "NEXT"; +20100 locate 21,3 : print "┏━━━━┓"; +20110 locate 21,4 : print "┃    ┃"; +20111 locate 21,5 : print "┃    ┃"; +20112 locate 21,6 : print "┃    ┃"; +20113 locate 21,7 : print "┃    ┃"; +20120 locate 21,8 : print "┗━━━━┛"; +20130 locate 21,10 : print "SCORE"; +29999 return + +30000 ' 駒の形 +30001 ' read - data 文も欲しくなる... +30002 ' データ形式 (7 words/駒) +30003 ' (センター座標からの x offset, y offset) × 3, 回転先駒データ位置 +30004 K = 23 * 12 : ' フィールド記憶領域の次に駒データを入れるベース位置 +30005 k = K +30006 ' 縦棒 ID = 0 +30007 @(k ) = 0 : @(k+1) = -2 : @(k+2) = 0 : @(k+3) = -1 +30008 @(k+4) = 0 : @(k+5) = 1 : @(k+6) = k+7: k = k + 7 +30009 ' 横棒 ID = 1 +30010 @(k ) = -1 : @(k+1) = 0 : @(k+2) = -2 : @(k+3) = 0 +30011 @(k+4) = 1 : @(k+5) = 0 : @(k+6) = k-7: k = k + 7 +30012 ' 佐渡島 ID = 2 +30013 @(k ) = 1 : @(k+1) = 0 : @(k+2) = 0 : @(k+3) = 1 +30014 @(k+4) = -1 : @(k+5) = 1 : @(k+6) = k+7: k = k + 7 +30015 ' 立ち佐渡島 ID = 3 +30016 @(k ) = -1 : @(k+1) = -1 : @(k+2) = -1 : @(k+3) = 0 +30017 @(k+4) = 0 : @(k+5) = 1 : @(k+6) = k-7: k = k + 7 +30018 ' 逆佐渡島 ID = 4 +30019 @(k ) = -1 : @(k+1) = 0 : @(k+2) = 0 : @(k+3) = 1 +30020 @(k+4) = 1 : @(k+5) = 1 : @(k+6) = k+7: k = k + 7 +30021 ' 立ち逆佐渡島 ID = 5 +30022 @(k ) = 1 : @(k+1) = -1 : @(k+2) = 1 : @(k+3) = 0 +30023 @(k+4) = 0 : @(k+5) = 1 : @(k+6) = k-7: k = k + 7 +30024 ' L ID=6 +30025 @(k ) = 0 : @(k+1) = -1 : @(k+2) = 0 : @(k+3) = 1 +30026 @(k+4) = 1 : @(k+5) = 1 : @(k+6) = k+7: k = k + 7 +30027 ' L+1 ID=7 +30028 @(k ) = 1 : @(k+1) = -1 : @(k+2) = 1 : @(k+3) = 0 +30029 @(k+4) = -1 : @(k+5) = 0 : @(k+6) = k+7: k = k + 7 +30030 ' L+2 ID=8 +30031 @(k ) = -1 : @(k+1) = -1 : @(k+2) = 0 : @(k+3) = -1 +30032 @(k+4) = 0 : @(k+5) = 1 : @(k+6) = k+7: k = k + 7 +30033 ' L+3 ID=9 +30034 @(k ) = 1 : @(k+1) = 0 : @(k+2) = -1 : @(k+3) = 0 +30035 @(k+4) = -1 : @(k+5) = 1 : @(k+6) = k-21: k = k + 7 +30036 ' 逆L ID=10 +30037 @(k ) = 0 : @(k+1) = -1 : @(k+2) = 0 : @(k+3) = 1 +30038 @(k+4) = -1 : @(k+5) = 1 : @(k+6) = k+7: k = k + 7 +30039 ' 逆L+1 ID=11 +30040 @(k ) = -1 : @(k+1) = 0 : @(k+2) = 1 : @(k+3) = 0 +30041 @(k+4) = 1 : @(k+5) = 1 : @(k+6) = k+7: k = k + 7 +30042 ' 逆L+2 ID=12 +30043 @(k ) = 1 : @(k+1) = -1 : @(k+2) = 0 : @(k+3) = -1 +30044 @(k+4) = 0 : @(k+5) = 1 : @(k+6) = k+7: k = k + 7 +30045 ' 逆L+3 ID=13 +30046 @(k ) = -1 : @(k+1) = -1 : @(k+2) = -1 : @(k+3) = 0 +30047 @(k+4) = 1 : @(k+5) = 0 : @(k+6) = k-21: k = k + 7 +30048 ' 凸 ID=14 +30049 @(k ) = 0 : @(k+1) = -1 : @(k+2) = -1 : @(k+3) = 0 +30050 @(k+4) = 1 : @(k+5) = 0 : @(k+6) = k+7: k = k + 7 +30051 ' 左凸 ID=15 +30052 @(k ) = 0 : @(k+1) = -1 : @(k+2) = -1 : @(k+3) = 0 +30053 @(k+4) = 0 : @(k+5) = 1 : @(k+6) = k+7: k = k + 7 +30054 ' T ID=16 +30055 @(k ) = 1 : @(k+1) = 0 : @(k+2) = -1 : @(k+3) = 0 +30056 @(k+4) = 0 : @(k+5) = 1 : @(k+6) = k+7: k = k + 7 +30057 ' ト ID=17 +30058 @(k ) = 1 : @(k+1) = 0 : @(k+2) = 0 : @(k+3) = -1 +30059 @(k+4) = 0 : @(k+5) = 1 : @(k+6) = k-21: k = k + 7 +30060 ' 田 ID=18 +30061 @(k ) = 0 : @(k+1) = -1 : @(k+2) = -1 : @(k+3) = -1 +30062 @(k+4) = -1 : @(k+5) = 0 : @(k+6) = k : k = k + 7 +31000 return + +32764 ' 結局仕様書をまとめないとコーディングはできないね。 +32765 ' そう単純じゃなかった。 +32766 ' Catch the Buzz - original on Macintosh +32767 ' reproduced with WONBE by Hirotaka JOE Ohkubo, 2000/12/07 + diff --git a/keywords.h b/keywords.h index c07a66b..f64fb7d 100644 --- a/keywords.h +++ b/keywords.h @@ -1,6 +1,8 @@ /* WONBE predefined keyword IDs */ -/* First Created: Nov.3,2000 by Nashiko */ -/* Copyright 2000 (c) by Pie Dey Co.,Ltd. */ +/* First Created: Nov.3,2000 by Pie Dey Co.,Ltd. */ + +/* This source code is distributed under GNU General Public License (GPL) */ +/* see http://www.gnu.org/ about GPL */ #define KEYWORD_IF 0x80 #define KEYWORD_PRINT 0x81 @@ -21,20 +23,35 @@ #define KEYWORD_SAVE 0x90 #define KEYWORD_LOAD 0x91 #define KEYWORD_MERGE 0x92 -#define KEYWORD_RANDOMIZE 0x93 +#define KEYWORD_RANDOMIZE 0x93 #define KEYWORD_EXIT 0x94 #define KEYWORD_DEBUG 0x95 #define KEYWORD_WAITVB 0x96 #define KEYWORD_FILES 0x97 -#define KEYWORD_AND 0xa0 -#define KEYWORD_OR 0xa1 -#define KEYWORD_XOR 0xa2 -#define KEYWORD_NOT 0xb0 +#define KEYWORD_PLAY 0x98 +#define KEYWORD_POKE 0x99 +#define KEYWORD_CALL 0x9a +#define KEYWORD_INT 0x9b +#define KEYWORD_TRON 0x9c +#define KEYWORD_TROFF 0x9d + +#define KEYWORD_AND 0xa0 +#define KEYWORD_OR 0xa1 +#define KEYWORD_XOR 0xa2 + +#define KEYWORD_NOT 0xb0 #define KEYWORD_SCAN 0xc0 #define KEYWORD_WAIT 0xc1 -#define KEYWORD_RND 0xc2 -#define KEYWORD_ABS 0xc3 +#define KEYWORD_RND 0xc2 +#define KEYWORD_ABS 0xc3 #define KEYWORD_TICK 0xc4 +#define KEYWORD_VARPTR 0xc5 +#define KEYWORD_VARSEG 0xc6 +#define KEYWORD_DSEG 0xc7 +#define KEYWORD_CSEG 0xc8 +#define KEYWORD_SSEG 0xc9 +#define KEYWORD_PEEK 0xca + #define KEYWORD_SCAN_A 0xd0 #define KEYWORD_SCAN_B 0xd1 #define KEYWORD_SCAN_X1 0xd2 @@ -45,15 +62,58 @@ #define KEYWORD_SCAN_Y2 0xd7 #define KEYWORD_SCAN_Y3 0xd8 #define KEYWORD_SCAN_Y4 0xd9 + +#define KEYWORD_AX 0xe0 +#define KEYWORD_BX 0xe1 +#define KEYWORD_CX 0xe2 +#define KEYWORD_DX 0xe3 +#define KEYWORD_SI 0xe4 +#define KEYWORD_DI 0xe5 +#define KEYWORD_DS 0xe6 +#define KEYWORD_ES 0xe7 +#define KEYWORD_DEFSEG 0xe8 + #define KEYWORD_THEN 0xf0 -#define KEYWORD_CHR 0xf1 -#define KEYWORD_TO 0xf2 +#define KEYWORD_CHR 0xf1 +#define KEYWORD_TO 0xf2 #define KEYWORD_STEP 0xf3 #define KEYWORDS_STATEMENT_FROM 0x80 -#define KEYWORDS_STATEMENT_TO 0x97 +#define KEYWORDS_STATEMENT_TO 0x9d #define KEYWORDS_2OP_FROM 0xa0 #define KEYWORDS_2OP_TO 0xa2 +/* +WONBE 中間言語フォーマット + + 中間言語は1行を単位として構築される + + プログラムの終わりは0x00 0x00でターミネートされる + + 1行の構造 + +WORD 行番号 (1-32767) +任意の中間コードの列 +BYTE 0x0d 行末ターミネータ + + 0x01〜0x03を除けば0x0dを単純検索するだけで行末が発見できる + +中間コード +0x00 (予約) +0x01 次にあるのは10進2バイト整数 +0x02 次にあるのは16進2バイト整数 +0x03 次にあるのは可変長文字列 0x00でターミネート +0x09 TAB +0x0d 行末ターミネータ +0x20〜0x2f そのコードの記号 +0x30〜0x39 ? +0x3a〜0x3f そのコードの記号 +0x40 @ +0x41〜0x5a A〜Z その名前の変数を示すシンボル +0x5b〜0x60 ? +0x61〜0x7A a〜z その名前の変数を示すシンボル +0x7b〜0x7f ? +0x80〜0xff キーワードの中間言語表現 +*/ /* end of keywords.h */ diff --git a/makefile b/makefile index c43a670..db89204 100644 --- a/makefile +++ b/makefile @@ -7,7 +7,7 @@ LINKER=..\..\vc15\bin\link CC=..\..\vc15\bin\cl ASM=..\..\vc15\bin\masm -CFLAGS=/ASw /O /Gs /DWW +CFLAGS=/ASw /O /Gs /DWW /DVC15 AFLAGS=-Mx -DDISPLAY_MODE_JAPANESE1 LFLAGS=/NOD /NOI /MAP diff --git a/testcall.wb b/testcall.wb new file mode 100644 index 0000000..678d43d --- /dev/null +++ b/testcall.wb @@ -0,0 +1,20 @@ +100 ' test machine language call +110 A=varptr(@(0)) +115 gosub 1000 +120 ax=1:bx=2:cx=3:dx=4:si=-1:di=-2 +130 call A +140 if ax <> 2 then debug "axの値が期待と違います":end +150 if bx <> 3 then debug "bxの値が期待と違います":end +160 if cx <> 4 then debug "cxの値が期待と違います":end +170 if dx <> 5 then debug "dxの値が期待と違います":end +180 if si <> 0 then debug "siの値が期待と違います":end +190 if di <> -1 then debug "diの値が期待と違います":end +900 debug "正常終了":end +1000 poke A+0,0x40 'inc ax +1010 poke A+1,0x43 'inc bx +1020 poke A+2,0x41 'inc cx +1030 poke A+3,0x42 'inc dx +1040 poke A+4,0x46 'inc si +1050 poke A+5,0x47 'inc di +1060 poke A+6,0xCB 'ret (FAR) +1090 return diff --git a/testint.wb b/testint.wb new file mode 100644 index 0000000..e0e1f54 --- /dev/null +++ b/testint.wb @@ -0,0 +1,26 @@ +100 cx=22 +110 ds=varseg(@(0)) +120 dx=varptr(@(0)) +125 ax=10*256 +130 int 0x17 +140 if ax<>0 then debug "BIOSがエラーを返しました":end +150 debug "name dump:"; +160 for i=0 to 15:debug peek(varptr(@(0))+i);",";:next:debug +162 debug "name char:"; +165 for i=0 to 15:debug chr(peek(varptr(@(0))+i));:next:debug +170 debug +180 debug "birth_year:";@(8) +190 debug "birth_month:";peek(varptr(@(0))+18) +200 debug "birth_day:";peek(varptr(@(0))+19) +210 debug "sex:"; +220 s = peek(varptr(@(0))+20) +230 if s=0 then debug "?" +240 if s=1 then debug "male" +250 if s=2 then debug "female" +260 debug "bloodtype:"; +270 b = peek(varptr(@(0))+21) +280 if b=0 then debug "?" +290 if b=1 then debug "A" +300 if b=2 then debug "B" +310 if b=3 then debug "O" +320 if b=4 then debug "AB" diff --git a/testpeekpoke.wb b/testpeekpoke.wb new file mode 100644 index 0000000..38770b4 --- /dev/null +++ b/testpeekpoke.wb @@ -0,0 +1,11 @@ +100 a=varptr(A) +110 s=varseg(A) +120 debug "変数Aはオフセット";a;",セグメント";s +130 A=0x1234 +140 defseg=s +150 if peek(a) <> 0x34 then debug "peekが異常です(!)":end +160 if peek(a+1) <> 0x12 then debug "peekが異常です(2)":end +170 poke a,0xfe +180 poke a+1,0xdc +190 if A <> 0xdcfe then debug "pokeが異常です":end +900 debug "テスト完了" diff --git a/win32text.c b/win32text.c index c233c57..7003113 100644 --- a/win32text.c +++ b/win32text.c @@ -1,8 +1,11 @@ // wonbe Win32 text emulation -// First Created: Nov.4,2000 by Nashiko -// Copyright 2000 (c) by Pie Dey Co.,Ltd. +/* First Created: Nov.4,2000 by Pie Dey Co.,Ltd. */ + +/* This source code is distributed under GNU General Public License (GPL) */ +/* see http://www.gnu.org/ about GPL */ #include +#include #include "win32text.h" #define SCREEN_SIZE_X (224/8) @@ -282,4 +285,104 @@ void win32_sys_wait( unsigned int val ) Sleep( val*10 ); } + +static BOOL bPlayingMIDI = FALSE; +static UINT wDeviceID; + +DWORD stopMIDIFile(HWND hwnd) +{ + if( bPlayingMIDI ) { + mciSendCommand(MCI_ALL_DEVICE_ID, MCI_CLOSE, MCI_WAIT, (DWORD)NULL); + bPlayingMIDI = FALSE; + } + return 0; +} + +DWORD playMIDIFile(HWND hWndNotify, LPSTR lpszMIDIFileName) +{ + DWORD dwReturn; + MCI_OPEN_PARMS mciOpenParms; + MCI_PLAY_PARMS mciPlayParms; + MCI_STATUS_PARMS mciStatusParms; + //MCI_SEQ_SET_PARMS mciSeqSetParms; + + // Open the device by specifying the device and filename. + // MCI will attempt to choose the MIDI mapper as the output port. + mciOpenParms.lpstrDeviceType = "sequencer"; + mciOpenParms.lpstrElementName = lpszMIDIFileName; + if (dwReturn = mciSendCommand((MCIDEVICEID)NULL, MCI_OPEN, + MCI_OPEN_TYPE | MCI_OPEN_ELEMENT, + (DWORD)(LPVOID) &mciOpenParms)) + { + // Failed to open device. Don't close it; just return error. + return (dwReturn); + } + + // The device opened successfully; get the device ID. + wDeviceID = mciOpenParms.wDeviceID; + + bPlayingMIDI = TRUE; + + // Check if the output port is the MIDI mapper. + mciStatusParms.dwItem = MCI_SEQ_STATUS_PORT; + if (dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, + MCI_STATUS_ITEM, (DWORD)(LPVOID) &mciStatusParms)) + { + mciSendCommand(wDeviceID, MCI_CLOSE, 0, (DWORD)NULL); + return (dwReturn); + } + + // The output port is not the MIDI mapper. + // Ask if the user wants to continue. + if (LOWORD(mciStatusParms.dwReturn) != MIDI_MAPPER) + { + //printf("Warning: The MIDI mapper is not available.\n"); + } + + // Begin playback. The window procedure function for the parent + // window will be notified with an MM_MCINOTIFY message when + // playback is complete. At this time, the window procedure closes + // the device. + mciPlayParms.dwCallback = (DWORD) hWndNotify; + if (dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, MCI_NOTIFY, + (DWORD)(LPVOID) &mciPlayParms)) + { + mciSendCommand(wDeviceID, MCI_CLOSE, 0, (DWORD)NULL); + return (dwReturn); + } + + return (0L); +} + +// "テキスト音楽「サクラ」"に含まれるdsakura.dllを用いてMMLを再生します +// サクラは以下より入手できます http://www.text2music.com/ +// dsakura.dllが無ければ音が出ないだけで、エラーにはなりません。 +void win32_play_mml( const char * mml ) +{ + static BOOL initialized = FALSE; + static HMODULE hmod = NULL; + static FARPROC pMMLtoMIDI = NULL; + if( !initialized ) { + HMODULE hmod = LoadLibrary("dsakura"); + if( hmod != NULL ) { + pMMLtoMIDI = GetProcAddress( hmod, "MMLtoMIDI" ); + } else { + printf("LoadLibrary(\"dsakura\") failed\n"); + } + initialized = TRUE; + } + if( pMMLtoMIDI != NULL ) { + char errmsg[256]; + BOOL b; + stopMIDIFile(hwnd); + b = (*pMMLtoMIDI)(mml,"$$$.mid",errmsg); + if( b == FALSE ) { + printf("dsakura: %s\n",errmsg); + } + playMIDIFile(hwnd, "$$$.mid"); + } else { + printf("play: %s\n", mml ); + } +} + // end of win32text.c diff --git a/win32text.h b/win32text.h index a781c2f..46a88eb 100644 --- a/win32text.h +++ b/win32text.h @@ -1,6 +1,8 @@ // wonbe Win32 text emulation -// First Created: Nov.4,2000 by Nashiko -// Copyright 2000 (c) by Pie Dey Co.,Ltd. +/* First Created: Nov.3,2000 by Pie Dey Co.,Ltd. */ + +/* This source code is distributed under GNU General Public License (GPL) */ +/* see http://www.gnu.org/ about GPL */ int createText(); void clearText(); @@ -11,5 +13,6 @@ unsigned short win32_wait(); unsigned short win32_scan(); unsigned int win32_get_tick_count(); void win32_sys_wait( unsigned int val ); +void win32_play_mml( const char * mml ); // end of win32text.h diff --git a/wonbe.c b/wonbe.c index 6ca8474..6121777 100644 --- a/wonbe.c +++ b/wonbe.c @@ -1,8 +1,14 @@ /* wonbe: WonderWitch Basic Environment */ -/* First Created: Nov.3,2000 by Nashiko */ -/* Copyright 2000 (c) by Pie Dey Co.,Ltd. */ +/* First Created: Nov.3,2000 by Pie Dey Co.,Ltd. */ -/* This source code is for both VC++6.0 and Turbo C 2.0 */ +/* This source code is distributed under GNU General Public License (GPL) */ +/* see http://www.gnu.org/ about GPL */ + +/* This source code is for: */ +/* Visual C++ 1.5 (for WW binary) */ +/* Visual C++ 6.0 (for Win32 binary) */ +/* Turbo C++ 1.0 (for WW binary, by Hirotaka JOE Ohkubo) */ +/* GNU Win32 gcc (for Win32 binary, by Hirotaka JOE Ohkubo) */ #include #include @@ -22,7 +28,18 @@ #include "win32text.h" #endif -char myVersion[] = "0.04"; +/* cygwin でなぜか stdarg.h が読み込まれてない & __GNUC__ が効かない... */ +#ifdef CYGWIN +#include +#endif + +char myVersion[] = "0.05"; + +#ifdef WW +#define NEWLINE "\xa\xd" +#else +#define NEWLINE "\n" +#endif #ifdef WW #define MEMMOVE mymemmove @@ -37,6 +54,7 @@ typedef unsigned char BYTE; #endif typedef unsigned short WORD; typedef signed short SHORT; +typedef unsigned long DWORD; #define EOL (0x0d) @@ -51,6 +69,14 @@ typedef void (*NEARPROC)(); #define WORKAREA_SIZE ((WORD)49152) #define LINE_SIZE (256) +/* PLAY statement support */ +#ifdef WW +#include +SoundIL soundIL; +extern BYTE *_heap; +BOOL soundAvailable; +#endif + /* 実行のみのモードで動いているとき (シリアル経由で端末が居ないとき) */ BOOL runtimeOnly; @@ -141,11 +167,13 @@ typedef struct { KEYWORDITEM keywordsA[] = { { KEYWORD_AND,"and" }, { KEYWORD_ABS,"abs" }, + { KEYWORD_AX,"ax"}, { 0,NULL } }; KEYWORDITEM keywordsB[] = { { KEYWORD_BREAK,"break" }, + { KEYWORD_BX, "bx" }, { 0,NULL } }; @@ -153,17 +181,26 @@ KEYWORDITEM keywordsC[] = { { KEYWORD_CHR,"chr" }, { KEYWORD_CLS,"cls" }, { KEYWORD_CONT,"cont" }, + { KEYWORD_CALL, "call" }, + { KEYWORD_CSEG, "cseg" }, + { KEYWORD_CX,"cx" }, { 0,NULL } }; KEYWORDITEM keywordsD[] = { { KEYWORD_DEBUG,"debug" }, + { KEYWORD_DSEG, "dseg" }, + { KEYWORD_DX, "dx" }, + { KEYWORD_DI, "di" }, + { KEYWORD_DS, "ds" }, + { KEYWORD_DEFSEG, "defseg" }, { 0,NULL } }; KEYWORDITEM keywordsE[] = { { KEYWORD_END,"end" }, { KEYWORD_EXIT,"exit" }, + { KEYWORD_ES, "es" }, { 0,NULL } }; @@ -181,6 +218,7 @@ KEYWORDITEM keywordsG[] = { KEYWORDITEM keywordsI[] = { { KEYWORD_IF,"if" }, + { KEYWORD_INT, "int" }, { 0,NULL } }; @@ -209,6 +247,9 @@ KEYWORDITEM keywordsO[] = { KEYWORDITEM keywordsP[] = { { KEYWORD_PRINT,"print" }, + { KEYWORD_PLAY,"play" }, + { KEYWORD_PEEK, "peek" }, + { KEYWORD_POKE, "poke" }, { 0,NULL } }; @@ -235,12 +276,23 @@ KEYWORDITEM keywordsS[] = { { KEYWORD_SCAN_Y4,"scan_y4" }, { KEYWORD_SCAN,"scan" }, /* scanはscna_Xより後になければならない */ { KEYWORD_SAVE,"save" }, + { KEYWORD_SSEG, "sseg" }, + { KEYWORD_SI, "si" }, { 0,NULL } }; + KEYWORDITEM keywordsT[] = { { KEYWORD_THEN,"then" }, { KEYWORD_TO,"to" }, { KEYWORD_TICK,"tick" }, + { KEYWORD_TRON,"tron" }, + { KEYWORD_TROFF,"troff" }, + { 0,NULL } +}; + +KEYWORDITEM keywordsV[] = { + { KEYWORD_VARPTR, "varptr" }, + { KEYWORD_VARSEG, "varseg" }, { 0,NULL } }; @@ -261,13 +313,13 @@ KEYWORDITEM * keywordsIndex[26] = { keywordsI, NULL, NULL, keywordsL, keywordsM, keywordsN, keywordsO, keywordsP, NULL, keywordsR, keywordsS, keywordsT, - NULL, NULL, keywordsW, keywordsX, + NULL, keywordsV, keywordsW, keywordsX, NULL, NULL }; /* インタラクティブモード時の1行バッファ */ BYTE waRawLine[LINE_SIZE]; -BYTE waCoockedLine[LINE_SIZE]; +BYTE waCookedLine[LINE_SIZE]; /* コードとデータを収める領域 */ WORD codeTop; @@ -338,87 +390,140 @@ WORD runLineNumber; // REQUEST_RUN_FILE or REQUEST_LOAD_FILE経由で処理するときだけTRUEとなる BOOL appendMode = FALSE; +// Read/Writeされる擬似変数の置き場所 +WORD defseg; +WORD registers[KEYWORD_ES-KEYWORD_AX+1]; + +// トレースモード(tron/troff) +BOOL traceFlag = FALSE; + +// マシン語アクセス関連 +#ifdef VC15 +// VC++1.5のときに使うコード +WORD getdseg() +{ + WORD s; + __asm mov s, ds; + return s; +} +WORD getsseg() +{ + WORD s; + __asm mov s, ss; + return s; +} +WORD getcseg() +{ + WORD s; + __asm mov s, cs; + return s; +} +#else +WORD getdseg() +{ + return 0; // DUMMY VALUE +} +WORD getsseg() +{ + return 0; // DUMMY VALUE +} +WORD getcseg() +{ + return 0; // DUMMY VALUE +} +#endif + /* エラー発生 */ void syntaxError() { - commonPrint(NULL, "Syntax Error in %d\x07\n", currentLineNumber ); + commonPrint(NULL, "Syntax Error in %d\x7" NEWLINE, currentLineNumber ); bForceToReturnSuper = TRUE; requestNextAction = REQUEST_INTERACTIVE; } void divideByZero() { - commonPrint(NULL, "Divide by 0 in %d\x07\n", currentLineNumber ); + commonPrint(NULL, "Divide by 0 in %d\x7" NEWLINE, currentLineNumber ); bForceToReturnSuper = TRUE; requestNextAction = REQUEST_INTERACTIVE; } void outOfArraySubscription() { - commonPrint(NULL, "Out of Array Subscription in %d\x07\n", currentLineNumber ); + commonPrint(NULL, "Out of Array Subscription in %d\x7" NEWLINE, currentLineNumber ); bForceToReturnSuper = TRUE; requestNextAction = REQUEST_INTERACTIVE; } void lineNumberNotFound( WORD lineNumber ) { - commonPrint(NULL, "Line Number %d not Found in %d\x07\n", lineNumber, currentLineNumber ); + commonPrint(NULL, "Line Number %d not Found in %d\x7" NEWLINE, lineNumber, currentLineNumber ); bForceToReturnSuper = TRUE; requestNextAction = REQUEST_INTERACTIVE; } void stackOverflow() { - commonPrint(NULL, "Stack Overflow in %d\x07\n", currentLineNumber ); + commonPrint(NULL, "Stack Overflow in %d\x7" NEWLINE, currentLineNumber ); bForceToReturnSuper = TRUE; requestNextAction = REQUEST_INTERACTIVE; } void stackUnderflow() { - commonPrint(NULL, "Stack Underflow in %d\x07\n", currentLineNumber ); + commonPrint(NULL, "Stack Underflow in %d\x7" NEWLINE, currentLineNumber ); bForceToReturnSuper = TRUE; requestNextAction = REQUEST_INTERACTIVE; } void nextWithoutFor() { - commonPrint(NULL, "Next without For in %d\x07\n", currentLineNumber ); + commonPrint(NULL, "Next without For in %d\x7" NEWLINE, currentLineNumber ); bForceToReturnSuper = TRUE; requestNextAction = REQUEST_INTERACTIVE; } void outOfMemory() { - commonPrint(NULL, "Out of memory in %d\x07\n", currentLineNumber ); + commonPrint(NULL, "Out of memory in %d\x7" NEWLINE, currentLineNumber ); bForceToReturnSuper = TRUE; requestNextAction = REQUEST_INTERACTIVE; } void loadError() { - commonPrint(NULL, "File Not Found or Load Error in %d\x07\n", currentLineNumber ); + commonPrint(NULL, "File Not Found or Load Error in %d\x7" NEWLINE, currentLineNumber ); bForceToReturnSuper = TRUE; requestNextAction = REQUEST_INTERACTIVE; } void cantContinue() { - commonPrint(NULL, "Can't Continue in %d\x07\n", currentLineNumber ); + commonPrint(NULL, "Can't Continue in %d\x7" NEWLINE, currentLineNumber ); bForceToReturnSuper = TRUE; requestNextAction = REQUEST_INTERACTIVE; } void saveError() { - commonPrint(NULL, "Save Erroor in %d\x07\n", currentLineNumber ); + commonPrint(NULL, "Save Erroor in %d\x7" NEWLINE, currentLineNumber ); bForceToReturnSuper = TRUE; requestNextAction = REQUEST_INTERACTIVE; } void paramError() { - commonPrint(NULL, "Parameter Erroor in %d\x07\n", currentLineNumber ); + commonPrint(NULL, "Parameter Erroor in %d\x7" NEWLINE, currentLineNumber ); + bForceToReturnSuper = TRUE; + requestNextAction = REQUEST_INTERACTIVE; +} + +void lineNumberZeroError() +{ + // このエラーはエディタが出すものなのでランタイムで発生することはあり得ない + // なので現在行番号を報告する意味がない + //commonPrint(NULL, "Invalid Line Number 0 in %d\x7" NEWLINE, currentLineNumber ); + commonPrint(NULL, "Invalid Line Number 0\x7" NEWLINE ); bForceToReturnSuper = TRUE; requestNextAction = REQUEST_INTERACTIVE; } @@ -460,10 +565,12 @@ BYTE * skipToEOL( BYTE * p ) } } -BYTE * skipToNextLine( BYTE * p ) -{ - return skipToEOL( p+4 ); // +4は行番号2バイト行長さ2バイト -} +// 短い関数をインライン展開しないコンパイラ向けの最適化としてマクロ化 +#define skipToNextLine(p) ( skipToEOL(p+4)+1 ) +//BYTE * skipToNextLine( BYTE * p ) +//{ +// return skipToEOL( p+4 ); // +4は行番号2バイト行長さ2バイト +//} #if 1 #define mytolower(ch) ((ch >= 'A' && ch <= 'Z')? ch - 'A' + 'a' : ch) @@ -485,12 +592,14 @@ void clearRuntimeInfo() { memset( globalVariables, 0, sizeof(globalVariables) ); memset( topLevelVariables, 0, sizeof(topLevelVariables) ); - memset( stacks, 0, sizeof(globalVariables) ); + memset( stacks, 0, sizeof(stacks) ); + memset( registers, 0, sizeof(registers) ); executionPointer = NULL; resumePointer = NULL; currentLineNumber = 0; localVariables = topLevelVariables; stackPointer = 0; + defseg = getdseg(); srand(0); } @@ -499,6 +608,9 @@ void processLineHeader() { if( !bInteractive ) { currentLineNumber = *((WORD *)executionPointer); + if( traceFlag ) { + commonPrint( NULL, "[%d]", currentLineNumber ); + } executionPointer += 4; // +4は行番号2バイト行長さ2バイト } else { currentLineNumber = 0; @@ -753,7 +865,7 @@ BOOL sourceDump( FILE FAR * fp, WORD from, WORD to ) p++; } } - b = commonPrint(fp,"\n"); + b = commonPrint(fp,NEWLINE); if( b == FALSE ) return FALSE; } return TRUE; @@ -809,6 +921,9 @@ SHORT calcValue() if( pvar == NULL ) return -1; return *pvar; } + if( ch >= KEYWORD_AX && ch <= KEYWORD_ES ) { + return registers[ch-KEYWORD_AX]; + } switch( ch ) { case 0x01: /* 次にあるのは10進2バイト整数 */ case 0x02: /* 次にあるのは16進2バイト整数 */ @@ -887,6 +1002,81 @@ SHORT calcValue() return 1024; case KEYWORD_SCAN_Y4: return 2048; + case KEYWORD_DEFSEG: + return defseg; + case KEYWORD_DSEG: + return getdseg(); + case KEYWORD_CSEG: + return getcseg(); + case KEYWORD_SSEG: + return getsseg(); + case KEYWORD_VARPTR: + case KEYWORD_VARSEG: + { + BOOL requestSeg; + SHORT * refer; + requestSeg = (ch == KEYWORD_VARSEG); + while( TRUE ) { + ch = *executionPointer++; + if( ch != ' ' && ch != '\t' ) break; + } + if( ch != '(' ) { + syntaxError(); + return -1; + } + while( TRUE ) { + ch = *executionPointer++; + if( ch != ' ' && ch != '\t' ) break; + } + if( ch == '@' ) { /* is it l-value? */ + SHORT * pvar; + pvar = getArrayReference(); + if( pvar == NULL ) return -1; + refer = pvar; + } else if( ch >= 'A' && ch <= 'Z' ) { + refer = &globalVariables[ch-'A']; + } else if( ch >= 'a' && ch <= 'z' ) { + refer = &localVariables[ch-'a']; + } else if( ch >= KEYWORD_AX && ch <= KEYWORD_ES ) { + refer = ®isters[ch-KEYWORD_AX]; + } else if( ch == KEYWORD_DEFSEG ) { + refer = &defseg; + } else { + syntaxError(); + return -1; + } + while( TRUE ) { + ch = *executionPointer++; + if( ch != ' ' && ch != '\t' ) break; + } + if( ch != ')' ) { + syntaxError(); + return -1; + } +#ifdef WW + if( requestSeg ) { + return getdseg(); + } else { + return (SHORT)refer; + } +#else + printf("varseg/varptr: %08x\n", refer ); + return 0; +#endif + } + case KEYWORD_PEEK: + { + SHORT t; + BYTE FAR * fulladdr; + t = calcValue(); + fulladdr = (BYTE FAR *)(((DWORD)defseg << 16) + (WORD)t); +#ifdef WW + return *fulladdr; +#else + printf("peek: %08x\n", fulladdr ); + return 0; +#endif + } } syntaxError(); return -1; @@ -1065,27 +1255,6 @@ void st_assignment( SHORT * pvar ) /* *pvar = val; } -void st_if() -{ - SHORT val; - BYTE ch; - val = expr(); - if( bForceToReturnSuper ) return; - while( TRUE ) { - ch = *executionPointer++; - if( ch != ' ' && ch != '\t' ) break; - } - if( ch != KEYWORD_THEN ) { - syntaxError(); - return; - } - if( val != 0 ) { - return; /* thenの次から継続実行する */ - } - /* 条件不成立につき、行末まで読み飛ばす */ - executionPointer = skipToEOL( executionPointer ); -} - void printOrDebug( BOOL bPrint ) { WORD lastChar; @@ -1170,7 +1339,7 @@ void printOrDebug( BOOL bPrint ) if( bPrint ) { ptextNewline(); } else { - commonPrint( NULL, "\r\n" ); + commonPrint( NULL, NEWLINE ); } } } @@ -1261,12 +1430,43 @@ void st_return() if( stacks[stackPointer].type == STACK_TYPE_GOSUB ) break; } executionPointer = stacks[stackPointer].returnPointer; - if( executionPointer >= waCoockedLine && executionPointer < waCoockedLine+LINE_SIZE ) { + if( executionPointer >= waCookedLine && executionPointer < waCookedLine+LINE_SIZE ) { bInteractive = TRUE; } localVariables = stacks[stackPointer].lastLocalVariables; } +void st_if() +{ + SHORT val; + BYTE ch; + val = expr(); + if( bForceToReturnSuper ) return; + while( TRUE ) { + ch = *executionPointer++; + if( ch != ' ' && ch != '\t' ) break; + } + if( ch != KEYWORD_THEN ) { + syntaxError(); + return; + } + if( val != 0 ) { + while( TRUE ) { + ch = *executionPointer; + if( ch != ' ' && ch != '\t' ) break; + executionPointer++; + } + if( ch == 0x01 ) { + // thenのあとに整数が直接書かれた場合は、それにgotoする。 + st_goto(); + return; + } + return; /* thenの次から継続実行する */ + } + /* 条件不成立につき、行末まで読み飛ばす */ + executionPointer = skipToEOL( executionPointer ); +} + void st_for() { BYTE ch; @@ -1376,7 +1576,7 @@ void st_end() /* breakステートメント: デバッグ用の中断 */ void st_break() { - commonPrint(NULL, "Break in %d\x07\n", currentLineNumber); + commonPrint(NULL, "Break in %d\x7" NEWLINE, currentLineNumber); bForceToReturnSuper = TRUE; requestNextAction = REQUEST_INTERACTIVE; resumePointer = executionPointer; /* contする場所はbreakの次。breakのみの例外処理 */ @@ -1568,7 +1768,7 @@ void st_waitvb() void st_files() { #ifdef WIN32 - commonPrint( NULL, "files statement not implemented in Win32\x07\n" ); + commonPrint( NULL, "files statement not implemented in Win32\x7" NEWLINE ); #endif #ifdef WW int i; @@ -1599,15 +1799,168 @@ void st_files() waRawLine[p++] = statbuf.info[q++]; } waRawLine[p++] = '\0'; - commonPrint( NULL, "%s,%ld,%d\n", waRawLine, statbuf.len, statbuf.count ); + commonPrint( NULL, "%s,%ld,%d" NEWLINE, waRawLine, statbuf.len, statbuf.count ); } } else { - commonPrint( NULL, "*File Access Error\x07\n" ); + commonPrint( NULL, "*File Access Error\x7" NEWLINE ); } } #endif } +void st_play() +{ + BYTE ch; + + ch = *executionPointer++; + while ( ch == ' ' || ch == '\t' ) { + ch = *executionPointer++; + } + if ( ch != 0x03 ) { + syntaxError(); + return; + } + +#ifdef WIN32 + win32_play_mml( executionPointer ); +#endif +#ifdef WW + if ( soundAvailable ) { + parse_mml( _heap, executionPointer, 0 ); + bgm_play( _heap, PLAY_SINGLE ); + } +#endif + + executionPointer += strlen(executionPointer)+1; +} + +void st_poke() +{ + SHORT addr, data; + BYTE ch; + BYTE FAR * fulladdr; + addr = expr(); + if( bForceToReturnSuper ) return; + while( TRUE ) { + ch = *executionPointer++; + if( ch != ' ' && ch != '\t' ) break; + } + if( ch != ',' ) { + syntaxError(); + return; + } + data = expr(); + if( bForceToReturnSuper ) return; + fulladdr = (BYTE FAR *)(((DWORD)defseg << 16) + (WORD)addr); +#ifdef WW + *fulladdr = data; +#else + printf("poke: %08x %02x\n", fulladdr, data ); +#endif +} + +void st_call() +{ + SHORT addr; + BYTE FAR * fulladdr; + addr = expr(); + if( bForceToReturnSuper ) return; + fulladdr = (BYTE FAR *)(((DWORD)defseg << 16) + (WORD)addr); +#ifdef WW +#ifdef VC15 +// VC++1.5のときに使うコード + __asm { + push si + push di + push bp + mov ax,registers[(KEYWORD_AX-KEYWORD_AX)*2] + mov bx,registers[(KEYWORD_BX-KEYWORD_AX)*2] + mov cx,registers[(KEYWORD_CX-KEYWORD_AX)*2] + mov dx,registers[(KEYWORD_DX-KEYWORD_AX)*2] + mov si,registers[(KEYWORD_SI-KEYWORD_AX)*2] + mov di,registers[(KEYWORD_DI-KEYWORD_AX)*2] + mov es,registers[(KEYWORD_ES-KEYWORD_AX)*2] + push ds + mov ds,registers[(KEYWORD_DS-KEYWORD_AX)*2] + call far ptr ss:[fulladdr] + pop ds + mov registers[(KEYWORD_AX-KEYWORD_AX)*2],ax + mov registers[(KEYWORD_BX-KEYWORD_AX)*2],bx + mov registers[(KEYWORD_CX-KEYWORD_AX)*2],cx + mov registers[(KEYWORD_DX-KEYWORD_AX)*2],dx + mov registers[(KEYWORD_SI-KEYWORD_AX)*2],si + mov registers[(KEYWORD_DI-KEYWORD_AX)*2],di + mov registers[(KEYWORD_ES-KEYWORD_AX)*2],es + pop bp + pop di + pop si + } +#else + // VC++ 1.5以外の処理系のためのコードは作っていません。欲しい人、自作しましょう +#endif +#else + printf("call: %08x\n", fulladdr ); +#endif +} + +void st_int() +{ + SHORT number; + number = expr(); + if( bForceToReturnSuper ) return; +#ifdef WW +#ifdef VC15 +// VC++1.5のときに使うコード + { + static BYTE specialIntCallCode[3] = { 0xcd, 0x00, 0xcb }; + DWORD specialPtr; + specialIntCallCode[1] = (BYTE)number; + specialPtr = (((DWORD)getdseg() << 16) + (WORD)specialIntCallCode); + __asm { + push si + push di + push bp + mov ax,registers[(KEYWORD_AX-KEYWORD_AX)*2] + mov bx,registers[(KEYWORD_BX-KEYWORD_AX)*2] + mov cx,registers[(KEYWORD_CX-KEYWORD_AX)*2] + mov dx,registers[(KEYWORD_DX-KEYWORD_AX)*2] + mov si,registers[(KEYWORD_SI-KEYWORD_AX)*2] + mov di,registers[(KEYWORD_DI-KEYWORD_AX)*2] + mov es,registers[(KEYWORD_ES-KEYWORD_AX)*2] + push ds + mov ds,registers[(KEYWORD_DS-KEYWORD_AX)*2] + call far ptr ss:[specialPtr] + pop ds + mov registers[(KEYWORD_AX-KEYWORD_AX)*2],ax + mov registers[(KEYWORD_BX-KEYWORD_AX)*2],bx + mov registers[(KEYWORD_CX-KEYWORD_AX)*2],cx + mov registers[(KEYWORD_DX-KEYWORD_AX)*2],dx + mov registers[(KEYWORD_SI-KEYWORD_AX)*2],si + mov registers[(KEYWORD_DI-KEYWORD_AX)*2],di + mov registers[(KEYWORD_ES-KEYWORD_AX)*2],es + pop bp + pop di + pop si + } + } +#else + // VC++ 1.5以外の処理系のためのコードは作っていません。欲しい人、自作しましょう +#endif +#else + printf("int: %04x\n", number ); +#endif +} + +void st_tron() +{ + traceFlag = TRUE; +} + +void st_troff() +{ + traceFlag = FALSE; +} + /* 行エディタ */ void editLine() { @@ -1620,10 +1973,17 @@ void editLine() // 一方、中間言語翻訳の結果は先頭に0x01で始まる10進整数が行番号として入っている // このギャップを転送時に解消しなければならない - // ここに来ているということは、waCoockedLine[0]が0x01つまり10進整数である // - assert( waCoockedLine[0] == 0x01 ); - wishLineNumber = *((WORD*)&waCoockedLine[1]); - p = waCoockedLine+3; + // ここに来ているということは、waCookedLine[0]が0x01つまり10進整数である // + assert( waCookedLine[0] == 0x01 ); + wishLineNumber = *((WORD*)&waCookedLine[1]); + + /* 行番号 0 はだめ */ + if ( wishLineNumber == 0 ) { + lineNumberZeroError(); + return; + } + + p = waCookedLine+3; //target = getLineReferenceFromLineNumber( wishLineNumber ); target = getInsertionPointFromLineNumber( wishLineNumber ); lineNumber = *((WORD*)target); @@ -1633,7 +1993,6 @@ void editLine() if( ch != ' ' && ch != '\t' ) break; } if( ch == EOL ) { - WORD delta; BYTE * from; /* removing the line */ if( lineNumber == 0 || lineNumber != wishLineNumber ) { @@ -1641,12 +2000,11 @@ void editLine() return; } from = skipToNextLine(target); - delta = from-target; MEMMOVE( target, from, (WORD)(dataTop-(from-wa)) ); - dataTop -= delta; + dataTop -= from-target; } else { WORD len; // プログラム領域上に収めるときのサイズ - len = skipToEOL(p)-waCoockedLine-1+2+1; //-1は0x01の分。+2は長さ情報。+1はEOL + len = skipToEOL(p)-waCookedLine-1+2+1; //-1は0x01の分。+2は長さ情報。+1はEOL if( lineNumber == 0 || lineNumber != wishLineNumber ) { /* insert new line */ if( dataTop + len >= WORKAREA_SIZE ) { @@ -1660,7 +2018,7 @@ void editLine() WORD lost; BYTE * nextline; int delta; - nextline = skipToNextLine(target)+1; + nextline = skipToNextLine(target); lost = nextline-target; delta = len-lost; if( dataTop + delta >= WORKAREA_SIZE ) { @@ -1671,11 +2029,11 @@ void editLine() dataTop += delta; } // まず行番号をコピーする - *((WORD*)target) = *((WORD*)&waCoockedLine[1]); + *((WORD*)target) = *((WORD*)&waCookedLine[1]); // 行の長さを収める *((WORD*)(target+2)) = len; // 残りをコピーする - MEMMOVE( target+4, waCoockedLine+3, (WORD)(len-4) ); + MEMMOVE( target+4, waCookedLine+3, (WORD)(len-4) ); } } @@ -1684,18 +2042,18 @@ void appendLine() { BYTE * target; WORD len; // プログラム領域上に収めるときのサイズ - len = skipToEOL(waCoockedLine+3)-waCoockedLine-1+2+1; //-1は0x01の分。+2は長さ情報。+1はEOL + len = skipToEOL(waCookedLine+3)-waCookedLine-1+2+1; //-1は0x01の分。+2は長さ情報。+1はEOL if( dataTop + len >= WORKAREA_SIZE ) { outOfMemory(); return; } target = &wa[dataTop-5]; // -5 is len of last-line-marker // まず行番号をコピーする - *((WORD*)target) = *((WORD*)&waCoockedLine[1]); + *((WORD*)target) = *((WORD*)&waCookedLine[1]); // 行の長さを収める *((WORD*)(target+2)) = len; // 残りをコピーする - MEMMOVE( target+4, waCoockedLine+3, (WORD)(len-4) ); + MEMMOVE( target+4, waCookedLine+3, (WORD)(len-4) ); dataTop += len; wa[dataTop-5] = 0; wa[dataTop-4] = 0; @@ -1705,10 +2063,10 @@ void appendLine() } /* 中間言語に翻訳する */ -BOOL convertInternalCode( BYTE * waCoockedLine, const BYTE * waRawLine ) +BOOL convertInternalCode( BYTE * waCookedLine, const BYTE * waRawLine ) { const BYTE * src = waRawLine; - BYTE * dst = waCoockedLine; + BYTE * dst = waCookedLine; while( TRUE ) { if( *src == '\0' ) break; if( *src == '\n' ) break; @@ -1879,7 +2237,13 @@ NEARPROC statements[KEYWORDS_STATEMENT_TO-KEYWORDS_STATEMENT_FROM+1] = { st_exit, st_debug, st_waitvb, - st_files + st_files, + st_play, + st_poke, + st_call, + st_int, + st_tron, + st_troff }; void interpreterMain() @@ -1926,8 +2290,14 @@ void interpreterMain() st_assignment( &globalVariables[ch-'A'] ); } else if( ch >= 'a' && ch <= 'z' ) { st_assignment( &localVariables[ch-'a'] ); + } else if( ch >= KEYWORD_AX && ch <= KEYWORD_ES ) { + st_assignment( ®isters[ch-KEYWORD_AX] ); + } else if( ch == KEYWORD_DEFSEG ) { + st_assignment( &defseg ); } else if( ch >= KEYWORDS_STATEMENT_FROM && ch <= KEYWORDS_STATEMENT_TO ) { (*(statements[ch-KEYWORDS_STATEMENT_FROM]))(); + } else if( ch == '?' ) { + st_debug(); } else { syntaxError(); } @@ -1940,30 +2310,36 @@ void interpreterMain() void interactiveMain( FILE FAR * fp ) { if( fp == NULL ) { - commonPrint(NULL,"OK\n"); + commonPrint(NULL,"OK" NEWLINE); } while( TRUE ) { BOOL b; + WORD l; if( fp == NULL ) { consoleInput( waRawLine, LINE_SIZE ); } else { char FAR * r; r = fgets( waRawLine, LINE_SIZE, fp ); if( r == NULL ) break; + /* ファイル中に LF があると残ってしまうのを消す */ + l = strlen(waRawLine)-1; + if ( waRawLine[l] == '\x0a' ){ + waRawLine[l] = '\0'; + } } #ifdef WW if( fp == NULL ) { - commonPrint( NULL, "\r\n" ); + commonPrint( NULL, NEWLINE ); } #endif /* 中間言語に翻訳する */ - b = convertInternalCode( waCoockedLine, waRawLine ); + b = convertInternalCode( waCookedLine, waRawLine ); if( b == FALSE ) { bForceToReturnSuper = FALSE; continue; } /* 数値で開始されているか? */ - if( waCoockedLine[0] == 0x01 ) { + if( waCookedLine[0] == 0x01 ) { /* 行エディタを呼び出す */ if( appendMode ) { appendLine(); @@ -1975,7 +2351,7 @@ void interactiveMain( FILE FAR * fp ) } } else { /* その行を実行する */ - executionPointer = waCoockedLine; + executionPointer = waCookedLine; interpreterMain(); } if( bForceToReturnSuper ) return; @@ -2004,6 +2380,7 @@ void do_new() { clearRuntimeInfo(); bInteractive = TRUE; + traceFlag = FALSE; codeTop = 0; wa[0] = 0; wa[1] = 0; @@ -2172,6 +2549,12 @@ int main( int argc, char *argv[] ) createText(); #endif #ifdef WW +#ifdef CURRENT_DIR_IS_RAM0 + // シンボルCURRENT_DIR_IS_RAM0を定義してビルドすると + // カレントディレクトリは/ram0で走る + // 定義しなければ/rom0で走る + chdir("/ram0"); +#endif text_screen_init(); b = entranceUI(); if( b == FALSE ) return 0; @@ -2179,20 +2562,35 @@ int main( int argc, char *argv[] ) comm_set_baudrate(1); comm_open(); } + + /* PLAY statement support */ + soundAvailable = FALSE; + if (open_sound_il(&soundIL) == E_FS_SUCCESS) { + soundAvailable = TRUE; + // sounddrv_init(); いらないならわざわざ呼ばない。 + sound_open(); + } #endif + ptextCLS(); if( requestNextAction == REQUEST_NO_ACTION ) { do_new(); } if( !runtimeOnly ) { - commonPrint(NULL,"ワンべぇ WonderWitch Tiny BASIC Environment Ver %s\n",myVersion); - commonPrint(NULL,"Copyright 2000 (c) by Pie Dey Co.,Ltd.\n"); + commonPrint(NULL,"ワンべぇ WonderWitch Tiny BASIC Environment Ver %s" NEWLINE,myVersion); + commonPrint(NULL,"Authors: Pie Dey Co.,Ltd., Hirotaka JOE Ohkubo" NEWLINE); + commonPrint(NULL,"This program is distributed under GNU General Public License" NEWLINE); } superMain(); #ifdef WIN32 deleteText(); #endif #ifdef WW + /* PLAY statement support */ + if (soundAvailable) { + sound_close(); + sounddrv_release(); + } if( !runtimeOnly ) { comm_close(); } diff --git a/wonbe.dsp b/wonbe.dsp index 3940a25..f2da906 100644 --- a/wonbe.dsp +++ b/wonbe.dsp @@ -50,7 +50,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Winmm.lib /nologo /subsystem:console /machine:I386 !ELSEIF "$(CFG)" == "wonbe - Win32 Debug" @@ -74,7 +74,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Winmm.lib /nologo /subsystem:console /debug /machine:I386 !ENDIF diff --git a/wonbe.exe b/wonbe.exe index 80b3fb2..ed662f8 100644 Binary files a/wonbe.exe and b/wonbe.exe differ diff --git a/wonbe.fx b/wonbe.fx index 61a31df..ff8530b 100644 Binary files a/wonbe.fx and b/wonbe.fx differ diff --git a/wonbe.txt b/wonbe.txt index dbcf3a3..8ab2572 100644 --- a/wonbe.txt +++ b/wonbe.txt @@ -1,15 +1,16 @@ ワンべぇ: WONBE, WonderWitch BASIC Environment - 暫定マニュアル Ver 0.04 - 2000年11月12日 + 暫定マニュアル Ver 0.05 + 2000年12月10日 株式会社ピーデー 川俣 晶 - Copyright 2000 (c) by Pie Dey Co.Ltd. + This software is distributed under GNU General Public License ●これは何か?  ワンべぇは、WonderWitch上で使用できる小型BASICインタプリタです。  WonderWitch上ですべての機能が稼働し、シリアルケーブル経由で接続された一般の通信ソフトで操作します。デバッグ済みのプログラムを実行する場合は、シリアルケーブルも通信ソフトも必要ありません。  WonderWitchのテキスト画面を扱う最小限度のステートメント(cls,locate,print)と、最小限度のボタン入力機能(wait,scan)を持ち、簡易なミニゲームが書けます。  動作テスト用にWin32上で動くバイナリーもありますが、これは、BASIC本体の動作確認用と割り切ってください。 + ドキュメントは、ちょっと見難いと思いますが、暫定版とします。 ●必要なもの ・開発時 @@ -46,7 +47,7 @@  データ型は、符号付き16bit整数だけです。  定数は、-32767〜32767の10進数か、0x0000〜0xffffの16進数で記述できます。-32768は変数には記憶できますが、ソースには書けません。(-32767-1のように書いてください)  変数は、グローバル変数として、A〜Zのアルファベット大文字1文字のものが26個あります。 - ローカル変数として、a〜zのアルファベット子文字1文字のものが26個あります。ローカル変数はgosubステートメントを実行したときに新しい領域が割り当てられ、returnステートメントを実行したときにgosubする前の領域が戻ってきます。 + ローカル変数として、a〜zのアルファベット小文字1文字のものが26個あります。ローカル変数はgosubステートメントを実行したときに新しい領域が割り当てられ、returnステートメントを実行したときにgosubする前の領域が戻ってきます。  配列変数は@(インデックス)という形式の1次元配列だけが使用できます。使用可能なサイズは、プログラム記憶領域(48Kバイト)の残りサイズに等しくなります。インデックスは0から始まります。(例: for i=0 to 9:print @(i):next)  演算子の優先順位は「単項演算子 > */ > +- > 比較演算子 > and,or,xor」となります。(比較演算子は、<と>と=で記述する演算子すべて)  計算順序は、括弧()を使って明示的に変更できます。 @@ -163,6 +164,29 @@ waitvb files  カレントディレクトリのファイル一覧をシリアルポートに送ります。単体で実行する場合には使えないデバッグ専用の機能です。 +play 文字列 + 引数の文字列をMMLとして再生します。使用可能にするには「● playステートメントを有効にする方法」を参照してください。 +例: play "cde" + +poke 式,式 + 最初の式をオフセット、2番目の式を値と見なし、システム変数defsegのセグメントに1バイトのメモリ書き込みを行います。 + Win32版では機能しません。 + 注意:csegのセグメントはフラッシュメモリなのでpokeでは書き込めません。 + +call 式 + 式をオフセットと見なし、システム変数defsegのセグメントにマシン語レベルのサブルーチンコール(FAR)を行います。コールする前にシステム変数AX,BX,CX,DX,SI,DI,DS,ESがそれぞれのレジスタに設定されます。リターン後のレジスタ状態はシステム変数AX,BX,CX,DX,SI,DI,ESに保存されます。(注:DSは戻りません) + Win32版では機能しません。 + +int 式 + 式を割り込み番号と見なし、マシン語レベルのシステム割り込み(int)を行います。WonderWitchのBIOSを呼び出すことができます。コールする前にシステム変数AX,BX,CX,DX,SI,DI,DS,ESがそれぞれのレジスタに設定されます。リターン後のレジスタ状態はシステム変数AX,BX,CX,DX,SI,DI,ESに保存されます。(注:DSは戻りません) + Win32版では機能しません。 + +tron + トレースモードをオンにします。トレースモードに入ると、新しい行の実行始めるごとに、行番号をデバッグコンソールに送信します。 + +troff + トレースモードをオフにします。 + ● 2項演算子  + - * / < > = <= >= <> and or xor @@ -177,6 +201,26 @@ rnd( abs(式)  式の絶対値を返します。 +varptr(変数) + 指定した変数のオフセットを返します。 + Win32版では機能しません。 + +varseg(変数) + 指定した変数のセグメントを返します。 + Win32版では機能しません。 + +peek(式) + 式をオフセットと見なし、システム変数defsegのセグメントから1バイトのメモリ読み出しを行います。 + Win32版では機能しません。 + +● システム変数 (読み書き可能) + +ax,bx,cx,dx,si,di,ds,es + callおよびintステートメントを使用する際にレジスタの値を指定したり、リターン後のレジスタの値を保存するために使用します。 + +defseg + peek関数、poke,callステートメントで使用されるセグメント値を保持します。初期値はdsegの値となります。 + ● システム変数 (読み出しのみ) scan @@ -202,25 +246,39 @@ scan_y4 tick  システムタイマーのtickを返します。ただし、本来のtick値は符号無し32bit整数であり、ここで得られるのは16bit符号あり整数であることに注意が必要です。はみ出たbitは捨てられます。 +dseg + 実行中のDSセグメントレジスタの値を返します。変数やワンべぇプログラムの中間言語コードはすべてこのセグメントにあります。 + Win32版では機能しません。 + +cseg + 実行中のCSセグメントレジスタの値を返します。ワンべぇのプログラム本体がこのセグメントにあります。 + Win32版では機能しません。 + +sseg + 実行中のSSセグメントレジスタの値を返します。マシン語スタックがこのセグメントにあります。 + Win32版では機能しません。 + ● ファイル保存時の拡張子  ワンべぇのソースフィルは、".wb"で終わるファイル名にしておいて下さい。loadなどのコマンドでは拡張子に関係なく読み込めますが、エントランスメニューに表示されるのは".wb"で終わるファイル名だけです。 -● 配布規則 - 現バージョンは品質が不明のテスト版です。 - ですので、以下のように扱ってください。 - (正規版でどうするかは未定です) +● playステートメントを有効にする方法 + sound.ilを、/rom0に転送しておいてください。このファイルが無いとplayステートメントを使用しても音が出ません。sound.ilが無ければ音が出ないだけで、プログラムは実行されます。 + Win32版では、クジラ飛行机さん作の"テキスト音楽「サクラ」"に含まれるdsakura.dllを用いてMMLを再生することができます。このソフトは、http://www.text2music.com/より入手できます。dsakura.dllは環境変数pathの通ったディレクトリならどこに置いても構いません。必要ファイルはこのDLLのみです。dsakura.dllが無ければ音が出ないだけで、プログラムは実行されます。ただし、MMLの仕様が完全に同じではないことに注意してください。なお、Win32版ではplayステートメント実行時にカレントディレクトリに$$$.midというファイルを生成します。実行終了後には削除して構いません。 -・転載 - 未完成品ですので、Internetやパソコン通信などへの転載は不可です。必ずhttp://www.piedey.co.jp/のサイトから入手するようにしてください。 -・雑誌掲載等 - ご相談下さい。 -・商業利用 - ご相談下さい。 -・自作ソフトの実行手段としてのワンべぇの添付 - 自作ソフトを配布するためにwonbe.fxを一緒に渡すことを許可します。アーカイブへの同梱、CD-Rメディアなどへの焼き込み、通信ケーブルによる転送、どれも可です。ただし、ワンべぇの動作に関しては何も保証はできませんので、リスクは自分で負ってください。利用にあたっては、ロイヤリティなどはありませんので、報告も送金も必要ありません。 +● 配布規則 + このバージョンより、本ソフトは、GNU General Public License (GPL)に従うものとしました。詳細はhttp://www.gnu.org/にあります。 + 要するに、誰でも、どんな目的にも使用して良いということです。ただし、本ソフトを売ってはいけません。また、ソースコードは必ず公開しなければなりません。商品の中に収録することは可ですが、本ソフトを利用者が自由にコピーして配布することを妨げてはなりません。 + 2000年12月現在、ソースコードは株式会社ピーデーの川俣晶(autumn@piedey.co.jp)が管理しています。有益なソースコードの修正をフィードバックしてくれれば、こちらのソースツリーに反映します。 ● 変更履歴 +2000年12月10日 Ver 0.05 +・Hirotaka JOE Ohkuboさんの差分(0.04j4)をマージ play文が使用可能に (要sound.il) +・?をキーワードdebugと見なす +・then直後が10進整数値ならgotoの省略を許す +・マシン語関連機能の追加 +・tron/troffコマンドの追加(実行行番号の表示) + 2000年11月12日 Ver 0.04 ・13など0x0dを含む行番号を削除しようとするとプログラムが壊れたバグを取った ・処理系をTurbo C2.0からVisual C++ 1.51に変更