- Hirotaka JOE Ohkubo's difference (0.04j4) can be merged with play statement (sound.il required)

- Consider? As the keyword debug
 - Allow goto to be omitted if immediately after it is a decimal integer value
 - Addition of machine language related functions
 - Add tron / troff command (display execution line number)

Version 0.05 - from wonbe005.lzh
This commit is contained in:
Kawamata Akira 2000-12-10 12:00:00 +09:00 committed by Godzil
parent 3bc39a53f1
commit b906d49ca1
14 changed files with 1111 additions and 110 deletions

32
Makefile.tcpp10 Normal file
View File

@ -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

290
ctb.wb Normal file
View File

@ -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 ' 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

View File

@ -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
 0x010x030x0d
0x00 ()
0x01 102
0x02 162
0x03 0x00
0x09 TAB
0x0d
0x200x2f
0x300x39 ?
0x3a0x3f
0x40 @
0x410x5a AZ
0x5b0x60 ?
0x610x7A az
0x7b0x7f ?
0x800xff
*/
/* end of keywords.h */

View File

@ -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

20
testcall.wb Normal file
View File

@ -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

26
testint.wb Normal file
View File

@ -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ªƒGƒ‰<C692>[‚ð•Ô‚µ‚Ü‚µ‚½":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"

11
testpeekpoke.wb Normal file
View File

@ -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 "テスト完了"

View File

@ -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 <windows.h>
#include <stdio.h>
#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

View File

@ -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

548
wonbe.c
View File

@ -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 <stdio.h>
#include <string.h>
@ -22,7 +28,18 @@
#include "win32text.h"
#endif
char myVersion[] = "0.04";
/* cygwin でなぜか stdarg.h が読み込まれてない & __GNUC__ が効かない... */
#ifdef CYGWIN
#include <stdarg.h>
#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 <il_sound.h>
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 = &registers[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( &registers[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();
}

View File

@ -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

BIN
wonbe.exe

Binary file not shown.

BIN
wonbe.fx

Binary file not shown.

View File

@ -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整数だけです。
 定数は、-3276732767の10進数か、0x00000xffffの16進数で記述できます。-32768は変数には記憶できますが、ソースには書けません。(-32767-1のように書いてください)
 変数は、グローバル変数として、AZのアルファベット大文字1文字のものが26個あります。
 ローカル変数として、azのアルファベット文字1文字のものが26個あります。ローカル変数はgosubステートメントを実行したときに新しい領域が割り当てられ、returnステートメントを実行したときにgosubする前の領域が戻ってきます。
 ローカル変数として、azのアルファベット文字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に変更