diff --git a/makefile b/makefile index d126588..c43a670 100644 --- a/makefile +++ b/makefile @@ -1,23 +1,34 @@ +INCLUDE=C:\vshare\ww\dev\WWitch\include +LIB=..\COMMON -# start up routine -C0WW_JAPANESE2=..\common\c0wwjpn2.obj +LIBS=libww.lib runtime.lib -C0WW=$(C0WW_JAPANESE2) +LINKER=..\..\vc15\bin\link +CC=..\..\vc15\bin\cl +ASM=..\..\vc15\bin\masm -LIBWW=@..\common\libww.rsp - -CFLAGS=-DWW -ms -zPCGROUP -zSDGROUP -zGDGROUP +CFLAGS=/ASw /O /Gs /DWW +AFLAGS=-Mx -DDISPLAY_MODE_JAPANESE1 +LFLAGS=/NOD /NOI /MAP all: wonbe.fx wonbe.fx: wonbe.bin mkfent wonbe.cf -wonbe.bin: wonbe.obj - tlink /m /c $(C0WW) wonbe, wonbe, wonbe, $(LIBWW) - exe2fbin wonbe.exe wonbe.bin +wonbe.bin: wonbe.obj vc15_rt.obj + $(LINKER) @<< +$(LFLAGS) vc15_rt.obj wonbe.obj,wonbe.sss,wonbe.map,$(LIBS); +<< + echo 0000 >0000.sss + exe2bin wonbe.sss wonbe.bin <0000.sss + echo remove temp file + del 0000.sss + del wonbe.sss wonbe.obj: wonbe.c - tcc -c $(CFLAGS) $(DEFINES) -IC:\vshare\ww\dev\WWitch\include wonbe.c + $(CC) -c $(CFLAGS) wonbe.c +vc15_rt.obj: vc15_rt.asm + $(ASM) $(AFLAGS) vc15_rt.asm; diff --git a/star.txt b/star.txt new file mode 100644 index 0000000..7bbb8b6 --- /dev/null +++ b/star.txt @@ -0,0 +1,133 @@ +STAR WITCH 〜ゴブリン帝国の野望〜 + +★★★ 準備 ★★★ + WonderSwan本体とWonderWitchを用意してください。 + wonbe.fxとstar.wbをWonderWitchに転送してください。 + Freya OSから「ワンべぇ」を選んでスタートさせてください。 + star.wbを選択してAボタンを押してください。 + 読み込みが完了するまでしばらく待ちます。 + +★★★ 目的 ★★★ + プレイヤーは、最強の宇宙戦艦WITCH号の艦長となって、ゴブリン帝国の宇宙戦艦を撃滅します。 + 宇宙空間はエリアと呼ばれる単位で区切られています。 + 一つのエリアに侵入したゴブリン戦艦をすべて撃滅すると、次のエリアに進むことができます。 + 10個のエリアからゴブリン戦艦を駆逐すると、プレイヤーの勝利となります。 + 逆に、戦闘途上で、WITCH号のエネルギー量がゼロになると、プレイヤーの敗北となります。 + +★★★ シンボル ★★★ + エリアマップ上では以下のシンボルで表示されます。 + +WITCH号 Wマーク +ゴブリン戦艦 Gマーク +輸送船 Tマーク +小惑星 *マーク + +★★★ 基本操作 ★★★ + Aボタンで確定 + Bボタンでキャンセル + X1〜4ボタンで上下左右 + + Win32版のワンべぇでプレイする場合は以下のようになります。 + スペースバーで確定 + ESCキーでキャンセル + 方向キーで上下左右 + +★★★ 移動 ★★★ + WITCH号には、エリア間を移動する「ジャンプ」の機能と、エリア内を移動する「バーニア」の機能があります。「ジャンプ」は、エリア内のすべてのゴブリン戦艦を撃沈しない限り使用できません。「バーニア」はいつでも使用できます。 + エリアは8×8の升目に区切られています。バーニアで移動中にこれから入ろうとする升目に小惑星や敵艦がいると、そこで緊急停止させられます。 + 「ジャンプ」する場合には、ジャンプ先の候補が3つ提示されますので、戦略をよく考えて選択します。 + 「バーニア」を使う場合は、方向と距離を数字で指定します。方向は0から360までの角度で指定します。右が0、上が90、左が180、下が270になります。5度単位で微妙な数値を指定することができます。距離は実際に動く升目の数を指定します。 + +★★★ 戦闘 ★★★ + ゴブリン戦艦のいるエリアにWITCH号が入ると、ゴブリン戦艦は情け容赦なく攻撃を加えてきます。 + ゴブリン戦艦の使用する武器は、指向性ウェーブ兵器です。これは、自艦の持つエネルギーを発射して、発射したのと同じ量だけWITCH号にダメージを与える兵器です。 + これに対して、WITCH号が使用できる武器は2種類あります。 + 一つはウェーブキヤノンと呼ばれる無指向性ウェーブ兵器です。これは、1回の攻撃で、エリア全体を攻撃できる広域兵器です。しかし、敵艦以外にもエネルギーが収束してしまうという欠点があります。たとえば、ゴブリン戦艦が2隻、小惑星が3個、輸送船が1隻いるとします。ここで、600のエネルギーをウェーブキヤノンで発射すると、それぞれの標的にエネルギーが均等に分かれ、ゴブリン戦艦はそれぞれ100のダメージを受けます。ウェーブキヤノンで使用した分のエネルギーは、WITCH号のエネルギーから差し引かれますので、敵の攻撃を受け止めたり、移動するためのエネルギーは残しておかねばなりません。 + ゴブリン戦艦は、艦内のエネルギーがゼロになると防御シールドが消えて破壊できます。ウェーブキヤノンで小惑星を破壊することはできません。輸送船はウェーブ吸収装置が取り付けられているので、ウェーブキヤノンでダメージを受けることはありません。 + もう一つの武器は、反応弾頭ミサイルです。これは、一度に1発しか発射できませんが、ゴブリン戦艦を一撃で確実にしとめることができる強力兵器です。また、小惑星や、輸送船も破壊することができます。ミサイルを発射するにあたってエネルギーは消費しません。WITCH号は最大で10発までこのミサイルを搭載することができます。ミサイルを発射する場合には、発射する方向を指定します。指定方法は「バーニア」による移動と同じです。 + +★★★ 補給 ★★★ + 輸送船と上下左右の4カ所のいずれかで隣接すると、輸送船よりエネルギーとミサイルの補給を受けることができます。隣接し続ける限り、毎ターンの最初にエネルギーとミサイルが満タンになります。 + 輸送船はステルス機能があるため、ゴブリン戦艦の攻撃を受けることはありませんが、そのかわり、一切の攻撃兵器を持っておらず、戦闘の手助けはできません。 + +★★★ ステータス値 ★★★ + 上部左右中央部に表示される数値の意味は以下の通りです。 +ENERGY WITCH号の残りエネルギー量 +MISSILE WITCH号の残りミサイル数 +LEFT あとクリアすべきエリアの数 +DAY 経過日数 + +★★★ 目指せ名艦長 ★★★ + このゲームでは、ただ単に勝利するだけなら難しくありません。 + クリア最短日数や、最多敵艦撃破などの条件を設定して、トライしてください。 + +★★★ 攻略のヒント ★★★ + +以 +下 +は +ど +う +し +て +も +ク +リ +ア +で +き +な +い +人 +だ +け +が +読 +ん +で +下 +さ +い +。 + +・輸送船とランデブーして大逆転 + 輸送船と接触すれば、事実上エネルギーもミサイルも使い放題です。使っても次のターンの開始時に回復されるので、どーんとウェーブキヤノンで大量のエネルギーを叩き付けてゴブリン戦艦を全滅させてしまいましょう。 + +・ウェーブキヤノンとミサイルどちらが得か? + ミサイルは1隻ずつしか攻撃できませんが、ウェーブキヤノンはすべての敵を同時攻撃できます。敵に囲まれたときに、少ないダメージで敵を倒すには、一見、ウェーブキヤノンが有利に見えます。しかし、ウェーブキヤノンは敵以外にもエネルギーを消費してしまうという弱点があるため、エネルギーの無駄遣いになりがちです。 + もし、ウェーブキヤノンで敵を仕留める場合は、敵にどんどん攻撃させ、敵艦のエネルギーが底をついたところで、少量のエネルギーでウェーブキヤノンを使うと無駄が少なくて済みます。 + しかし、何と言ってもエネルギーを使わないで敵を仕留めるミサイルを使うのが最もエネルギーの効率が良いのは言うまでもありません。エリアマップから正しい発射角度を瞬時に判断できるようになってこそ、名艦長と言えるでしょう。 + +・ウェーブキヤノンとミサイルの使い分けの判断は? + ミサイルで1隻ずつ沈めるのが基本です。ウェーブキヤノンを使うのは例外的な状況と考えるべきです。以下が代表的な状況です。 + →輸送船とランデブーしているとき + →補給直後でエネルギーがたっぷりあるとき + →小惑星などが邪魔をしてミサイル攻撃しにくいとき + →小惑星などが少なく、効率よくエネルギーを敵に叩き込めるとき + →ミサイルの残りがゼロのとき + →敵の残りエネルギーが極めて少ないとき + +・輸送船を破壊するな + ミサイルの方向を間違えて輸送船に命中してしまうと、ペナルティとして、輸送船の乗組員の救助のために10日間の日数が加算されます。最短日数クリアを目指す場合は、注意してください。 + +・常に輸送船のいるエリアを目指すべきか? + エネルギーが満タンであれば、そう簡単にやられることはありません。輸送船がいるエリアよりも敵が多いエリアを選んでジャンプしましょう。最多敵艦撃破を目指す場合は、残りエネルギーが十分かどうか特に注意して判断しましょう。 + +・小惑星はただの飾りか? + 小惑星の多い少ないは、戦い方に大きな影響を及ぼします。小惑星が多いと、いろいろな問題が起きます。 + →輸送船とランデブーする邪魔になる + →ミサイル攻撃の邪魔になる + →ウェーブキヤノンのエネルギーに無駄が増える + ですので、他の条件が同じであれば、小惑星の少ないエリアにジャンプする方が有利と言えます。 + +・小惑星を破壊せよ + 輸送船とランデブーしたいのに小惑星が邪魔だ、というときは、ミサイルで小惑星を破壊してしまいましょう。2回に分けて迂回して移動すると日数が余計に掛かります。最短日数クリアを目指す場合は、注意してください。 + +・ゴブリン戦艦残りエネルギー量を正確に知りたいとき + ウェーブキヤノンで攻撃すると、ゴブリン戦艦に与えたダメージの他に、各艦の残りエネルギー量も表示されます。少ないエネルギー量で軽くウェーブキヤノンで攻撃してみると良いでしょう。 + +・ゴブリン戦艦の戦術 + ゴブリン戦艦は敵を発見すると、ひたすら指向性ウェーブ兵器で攻撃を繰り返します。その際、自艦の持つエネルギーのうち、どの程度のエネルギー量を叩き付けてくるかは一定しません。また、最初にどの程度のエネルギー量を持っているかも一定しません。だいたい初期エネルギー量は500前後で、1回の攻撃では所持エネルギーの半分程度で攻撃してきますが、それは平均値でしかありません。 + しかし、エネルギーがゼロに近づいた場合には、艦の自滅を回避するために攻撃を取りやめます。存在するのに攻撃を仕掛けてこないゴブリン戦艦がある場合は、エネルギーがゼロに近いので、わずかなエネルギーをウェーブキヤノンで叩き付けるだけで撃沈できます。 + ゴブリン戦艦は命じられた場所を文字通り死守するので、戦闘中に移動することはありません。 + diff --git a/star.wb b/star.wb new file mode 100644 index 0000000..fba605e --- /dev/null +++ b/star.wb @@ -0,0 +1,501 @@ +cls:print"Loading STAR WITCH..." +locate 10,10:print "○○○○"; +100 cls:gosub 17000 'オープニング +1000 cls +1010 print "┏━━━━━━━━━┳━━━━━━━┳━━━━━━━━┓"; +1020 print "┃ 12345678┃       ┃        ┃"; +1030 print "┃1        ┃ENERGY ┃   ジャンプ ┃"; +1040 print "┃2        ┃       ┃        ┃"; +1050 print "┃3        ┃MISSILE┃   バーニア ┃"; +1060 print "┃4        ┃       ┃        ┃"; +1070 print "┃5        ┃LEFT   ┃   ウェーブ ┃"; +1080 print "┃6        ┃       ┃        ┃"; +1090 print "┃7        ┃DAY    ┃   ミサイル ┃"; +1100 print "┃8        ┃       ┃        ┃"; +1110 print "┣━━━━━━━━━┻━━━━━━━┻━━━━━━━━┫"; +1120 print "┃                          ┃"; +1130 print "┃                          ┃"; +1140 print "┃                          ┃"; +1150 print "┃                          ┃"; +1160 print "┃                          ┃"; +1170 print "┗━━━━━━━━━━━━━━━━━━━━━━━━━━┛"; +1175 print "   STAR WITCH 〜ゴブリン帝国の野望〜"; +1180 rem 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 +1190 rem +2000 rem 初期化 +2005 randomize tick +2010 E=4000 'EはWITCH号のエネルギー +2020 M=10 'MはWITCH号の所持ミサイル +2030 L=10 'Lはクリアすべきエリアの残り数 +2040 D=1 'Dは現在の日数 (1アクション1日) +2042 S=0 'WITCH号のX位置 +2044 T=0 'WITCH号のY位置 +2050 A=0 '@(A)〜@A(A+8*8-1)までが現在エリアの内容 +2060 '0:なし -1:小惑星 -2:輸送船 +2061 '正数はゴブリン戦艦でエネルギー量 +2065 W=A+8*8 'ワークエリアに使って良い配列の先頭位置 +2070 B=0 'エリア作成時の輸送船の数 +2080 G=0 'エリア作成時のゴブリン戦艦の数 +2090 S=1+rnd(4) 'エリア作成時の小惑星の数 +2095 H=0 '通算の撃破ゴブリン戦艦数 +2100 P=11 'メッセージエリアのY位置 (良く参照されるので変数に置く) +2200 rem エリア進入 +2210 gosub 10000 +3000 rem ターン開始 +3010 gosub 25000 'ステータス更新 +3020 gosub 12000 '補給チェックと実行 +3030 gosub 11000 '敵の攻撃 +3100 rem コマンド選択 +3105 gosub 20000:locate 2,P+2:print "艦長、ご指示を"; +3110 c=0 +3120 locate 20, 2+(c*2):print "→"; +3200 s=wait +3205 locate 20, 2+(c*2):print " "; +3210 if s and scan_a then goto 4000+(c*1000) +3220 if s and scan_x1 then c=c-1:if c<0 then c=3 +3230 if s and scan_x3 then c=c+1:if c>3 then c=0 +3290 goto 3120 +4000 '*******ジャンプ******* +4010 f=0 +4020 for y=0 to 7:for x=0 to 7 +4030 if @(A+x+y*8) > 0 then f=f+1 +4040 next:next +4050 if f=0 then goto 4200 +4060 gosub 20000 +4070 locate 2,P+1:print "艦長!"; +4080 locate 2,P+3:print "ゴブリン戦艦がまだ";f;"隻もいます!" +4090 d=wait +4100 gosub 20000 +4110 goto 3100 +4200 ' 行き先候補 +4210 gosub 20000 +4215 locate 2,P:print "目的地を指示してください" +4220 for i=0 to 2 +4230 @(W+i*3)=1+rnd(5) 'ゴブリン戦艦1〜5隻 +4240 @(W+i*3+1)=0:if rnd(3)=0 then @(W+i*3+1)=1 '輸送船は1/3の確率 +4250 @(W+i*3+2)=1+rnd(4) '小惑星1〜5個 +4260 locate 4,P+1+i +4270 print "ゴブリン";@(W+i*3); +4280 print " 輸送船";@(W+i*3+1); +4290 print " 小惑星"@(W+i*3+2); +4300 next +4400 rem 候補を選ぶ +4410 c=0 +4420 locate 2, P+1+c:print "→"; +4500 s=wait +4505 locate 2, P+1+c:print " "; +4510 if s and scan_a then goto 4600 +4520 if s and scan_x1 then c=c-1:if c<0 then c=2 +4530 if s and scan_x3 then c=c+1:if c>2 then c=0 +4590 goto 4420 +4600 ' 次のエリアに行く +4610 B=@(W+c*3+1) +4620 G=@(W+c*3) +4630 S=@(W+c*3+2) +4700 gosub 20000 +4710 locate 2,P+1:print "ハイパースペース・ドライブ"; +4720 locate 2,P+3:print "  スタンバイOK!" +4730 d=wait +4740 gosub 20000 +4750 locate 2,P+2:print "次のエリアにジャンプします"; +4760 d=wait +4780 gosub 20000 +4785 for y=0 to 7:for x=0 to 7:locate 2+x,2+y:print "※";:next:next +4790 waitvb 75 +4795 if E>10 then E=E-10:goto 4800 +4796 locate 2,P+1:print "艦長! エネルギーが足りません!"; +4797 locate 4,P+3:print "通常空間に復帰できません!!"; +4798 d=wait:goto 19000 +4800 locate 2,P+2:print "ジャンプ成功! レーダー動作します"; +4810 d=wait +4820 gosub 20000 +4890 D=D+1:L=L-1:goto 2200 +locate 10,10:print "●○○○"; +5000 '******バーニア******* +5010 gosub 20000 +5020 locate 2,P+1:print "エリア内移動・スタンバイ"; +5030 locate 2,P+3:print "コースは? (0-360)"; +5040 X=21:Y=P:gosub 21000 +5050 if Z<0 then goto 3100 'キャンセルされた +5060 if Z<=360 then s=Z:goto 5100 +5070 gosub 20000 +5080 locate 2,P+1:print "艦長!"; +5090 locate 2,P+3:print "コースは0から360までです!"; +5095 d=wait:goto 5010 +5100 gosub 20000 +5110 locate 2,P+1:print "エリア内移動・スタンバイ"; +5120 locate 2,P+3:print "距離は? (1-12)"; +5130 X=21:Y=P:gosub 21000 +5140 if Z<0 then goto 5010 'キャンセルされた +5145 if Z>E+1 then goto 5190 +5150 if Z>=1 and Z<=12 then l=Z:E=E-l:goto 5200 +5155 gosub 20000 +5160 locate 2,P+1:print "艦長!"; +5170 locate 2,P+3:print "距離は1から12までです!"; +5180 d=wait:goto 5100 +5190 gosub 20000 +5192 locate 2,P+1:print "艦長!"; +5194 locate 2,P+3:print "エネルギーが足りません!"; +5198 d=wait:goto 5100 +5200 '移動アニメーション +5210 gosub 20000 +5215 'locate 2+S,2+T:print " "; +5220 X=s:gosub 23000:a=Y +5230 X=s:gosub 22000:b=-Y '反時計回りにしたいのでマイナス +5235 c=S:d=T '最後に有効であった座標を持つ +5240 i=1:j=0 'iは本当の移動距離。jは見かけ上の移動距離 +5250 x=S+a*i/100 +5260 y=T+b*i/100 +5261 'debug S,T,x,y,a,b,i,s +5262 if x<0 or x>7 or y<0 or y>7 then goto 5400 +5264 if @(A+x+y*8)=0 then goto 5270 +5266 gosub 20000:locate 2,P+2:print "衝突回避! 緊急停止!";d=wait +5268 goto 5400 'ループを強制終了させる +5270 if c=x and d=y then goto 5300 '見かけ上の移動が起きていない +5272 j=j+1 +5275 locate 2+x,2+y:print "W"; +5280 locate 2+c,2+d:print " ";:c=x:d=y +6285 D=D+1:gosub 25000 +5290 waitvb 75 +5300 i=i+1:if j=1 and Z<=E-1 then s=Z:goto 6100 +6070 gosub 20000 +6080 locate 2,P+1:print "艦長!"; +6090 locate 2,P+3:print " エネルギー量は1から";E-1;"までです!"; +6095 d=wait:goto 6010 +6100 gosub 20000 +6110 ' 存在するオブジェクト数を数える +6120 f=0 +6130 for y=0 to 7:for x=0 to 7 +6140 if @(A+x+y*8) <> 0 then f=f+1 +6150 next:next +6160 e=s/f:if e<1 then e=1 'eは1標的あたりの攻撃量 +6170 gosub 20000 +6180 locate 2,P+2:print "ウェーブキヤノン・発射!"; +6190 d=wait +6200 for y=0 to 7:for x=0 to 7 +6210 if @(A+x+y*8) <= 0 then goto 6400 +6220 gosub 20000 +6230 locate 2,P+1:print "(";x+1;",";y+1;")のゴブリン戦艦にダメージ";e; +6240 @(A+x+y*8)=@(A+x+y*8)-e:if @(A+x+y*8)<=0 then @(A+x+y*8)=0:goto 6300 +6245 locate 4,P+3:print "(残りエネルギー";@(A+x+y*8);")"; +6250 d=wait +6290 goto 6400 +6300 locate 4,P+3:print "ゴブリン戦艦、撃沈!";:H=H+1 +6350 X=x:Y=y:gosub 24000 '爆発 +6400 next:next +6900 E=E-s: +6910 if L=0 then gosub 26000:if Y=0 then goto 18000 +6920 D=D+1:goto 3000 +locate 10,10:print "●●○○"; +7000 '******ミサイル****** +7010 if M>0 then goto 7100 +7020 gosub 20000 +7030 locate 2,P+1:print "艦長!"; +7040 locate 2,P+3:print "ミサイルの残弾はゼロです!"; +7050 d=wait +7090 goto 3100 +7100 gosub 20000 +7110 locate 2,P+1:print "ミサイル・スタンバイ"; +7120 locate 2,P+3:print "コースは? (0-360)"; +7130 X=21:Y=P:gosub 21000 +7140 if Z<0 then goto 3100 'キャンセルされた +7150 if Z<=360 then s=Z:goto 7200 +7160 gosub 20000 +7170 locate 2,P+1:print "艦長!"; +7180 locate 2,P+3:print "コースは0から360までです!"; +7190 d=wait:goto 7100 +7200 '移動アニメーション +7205 M=M-1:gosub 25000 +7210 gosub 20000 +7220 X=s:gosub 23000:a=Y +7230 X=s:gosub 22000:b=-Y '反時計回りにしたいのでマイナス +7235 i=1 +7240 c=S:d=T '最後に有効であった座標を持つ +7250 x=S+a*i/100 +7260 y=T+b*i/100 +7270 'debug S,T,x,y,a,b,i,s +7280 if x<0 or x>7 or y<0 or y>7 then goto 7500 +7290 if @(A+x+y*8)<>0 then goto 7600 +7320 if c=x and d=y then goto 7370 '見かけ上の移動が起きていない +7340 locate 2+x,2+y:print "M"; +7350 waitvb 75 +7360 locate 2+x,2+y:print " ";:c=x:d=y +7370 i=i+1:goto 7250 +7400 goto 3000 +7500 'はずれ! +7510 gosub 20000 +7515 locate 2,P+1:print "艦長!"; +7520 locate 4,P+3:print "攻撃は失敗です!"; +7530 d=wait +7590 D=D+1:goto 3000 +7600 'あたり! +7610 gosub 20000 +7620 locate 2,P+1:print "艦長!"; +7630 locate 4,P+3 +7640 if @(A+x+y*8)=-1 then print "小惑星に命中しました!"; +7650 if @(A+x+y*8)=-2 then print "輸送船に命中しました!"; +7660 if @(A+x+y*8)>0 then print "ゴブリン戦艦に命中しました!"; +7670 X=x:Y=y:gosub 24000 '爆発 +7680 'd=wait +7690 gosub 20000 +7700 locate 4,P+2 +7710 if @(A+x+y*8)=-1 then print "小惑星の消滅を確認!"; +7720 if @(A+x+y*8)=-2 then print "輸送船乗組員の救助のため10日必要です";:D=D+1 +7730 if @(A+x+y*8)>0 then print "ゴブリン戦艦を撃沈!";:H=H+1 +7740 @(A+x+y*8)=0 'そこにはもう何もない +7750 d=wait +7760 if L=0 then gosub 26000:if Y=0 then goto 18000 +7790 D=D+1:goto 3000 + +10000 rem エリア作成 +10005 for y=0 to 7:for x=0 to 7:@(A+x+y*8)=0:next:next +10010 if B=0 then goto 10100 +10020 for i=0 to B-1 +10030 x=rnd(8):y=rnd(8) +10040 if @(A+x+y*8) <> 0 then goto 10030 +10050 @(A+x+y*8)=-2 +10060 next +10100 if G=0 then goto 10200 +10105 for i=0 to G-1 +10110 x=rnd(8):y=rnd(8) +10120 if @(A+x+y*8) <> 0 then goto 10110 +10130 @(A+x+y*8)=400+rnd(200) 'ゴブリン戦艦のエネルギー初期値 +10140 next +10200 for i=0 to S-1 +10210 x=rnd(8):y=rnd(8) +10220 if @(A+x+y*8) <> 0 then goto 10210 +10230 @(A+x+y*8)=-1 +10240 next +10250 'WITCH号の位置を確定 +10260 S=rnd(7):T=rnd(7) +10270 if @(A+S+T*8) <> 0 then goto 10260 +10300 gosub 10500 +10400 return +10500 'レーダー作動 +10510 for y=0 to 7:for x=0 to 7 +10520 locate x+2,y+2 +10530 t=@(A+x+y*8) +10540 if t=0 then print " "; +10550 if t=-1 then print "*"; +10560 if t=-2 then print "T"; +10570 if t>0 then print "G"; +10580 next:next +10590 locate S+2,T+2:print "W"; +10600 return + +11000 '*****敵の攻撃***** +11010 for y=0 to 7:for x=0 to 7 +11020 if @(A+x+y*8) <= 2 then goto 11900 +11025 n=@(A+x+y*8)/4+rnd(@(A+x+y*8)/2):if n<1 then 11900 +11030 gosub 20000 +11040 locate 2,P+1:print "(";x+1;",";y+1;")のゴブリン戦艦よりの攻撃!"; +11050 d=wait +11070 locate 4,P+3:print "WITCH号に";n;"のダメージ!"; +11075 @(A+x+y*8)=@(A+x+y*8)-n +11080 E=E-n:if E<0 then E=0 +11090 gosub 25000 +11100 d=wait +11110 if E>0 then goto 11900 +11120 gosub 20000 +11130 locate 2,P+1:print "艦長!"; +11130 locate 4,P+3:print "エネルギーがもうありません!"; +11140 gosub 20000 +11150 locate 2,P+1:print "防御バリア機能停止"; +11160 locate 4,P+3:print "WITCH号の船体が砕けます!"; +11170 X=S:Y=T:gosub 24000 '爆発 +11180 gosub 20000 +11190 goto 19000 'BAD ENDING +11900 next:next +11910 return + +locate 10,10:print "●●●○"; + +12000 '補給チェックと実行 +12020 f=0 +12030 if S>0 then if @(A+(S-1)+T*8)=-2 then f=1 +12040 if S<7 then if @(A+(S+1)+T*8)=-2 then f=1 +12050 if T>0 then if @(A+S+(T-1)*8)=-2 then f=1 +12060 if T<7 then if @(A+S+(T+1)*8)=-2 then f=1 +12070 if f=0 then return +12080 gosub 20000 +12090 locate 2,P+1:print "艦長!"; +12100 locate 4,P+3:print "輸送船から補給を受けます。"; +12110 d=wait +12120 E=4000:M=10 +12130 gosub 25000 'ステータス更新 +12190 return + +17000 'OPENING +17010 cls +17020 for i=0 to 1 +17030 locate 2,2:print "緊急指令!" +17040 waitvb 30 +17050 locate 2,2:print "     " +17060 waitvb 30 +17070 next +17100 locate 2,2:print "緊急指令!" +17110 cls:print +17120 waitvb 30:print " かねてより":print +17130 waitvb 30:print " 我が地球連邦政府に敵対していた":print +17140 waitvb 30:print " 凶悪なゴブリン帝国が":print +17150 waitvb 30:print " 多数の宇宙戦艦で侵攻してきた":print +17155 print +17160 waitvb 30:print " 連邦艦隊ナンバーワン艦長の君に命じる":print +17170 waitvb 30:print " 最新鋭戦艦WITCH号を指揮し":print +17180 waitvb 30:print " 侵入したゴブリン戦艦を撃破せよ" +17190 d=wait + +17200 cls +17210 for i=0 to 4 +17220 if i=4 then locate 2, 2:print"  ■■■ ■■■■■  ■    ■■■■" +17230 if i=3 then locate 2, 3:print" ■      ■   ■ ■   ■   ■" +17240 if i=2 then locate 2, 4:print"  ■■■   ■   ■■■   ■■■■" +17250 if i=1 then locate 2, 5:print"     ■  ■  ■   ■  ■  ■" +17260 if i=0 then locate 2, 6:print"  ■■■   ■ ■     ■ ■   ■" +17270 if i=0 then locate 2, 9:print"■  ■  ■ ■ ■■■  ■■■   ■  ■" +17280 if i=1 then locate 2,10:print"■ ■ ■ ■ ■  ■  ■   ■  ■  ■" +17290 if i=2 then locate 2,11:print"■ ■ ■ ■ ■  ■  ■      ■■■■" +17300 if i=3 then locate 2,12:print"■ ■ ■ ■ ■  ■  ■   ■  ■  ■" +17310 if i=4 then locate 2,13:print" ■   ■  ■  ■   ■■■   ■  ■" +17320 waitvb 30:next +17330 locate 9,15:print "〜ゴブリン帝国の野望〜"; +17340 d=wait +17400 cls +17410 print " ***WITCH号の最新装備を紹介する***":print +17420 waitvb 30:print " 量子レーダー:" +17430 print "  W←WITCH号 *←小惑星" +17440 print "  G←ゴブリン戦艦 T←輸送船":print +17450 waitvb 30:print " 超空間ジャンプドライブ:" +17460 print "  エリア内の敵を全滅させたら次のエリアに進める。":print +17470 waitvb 30:print " バーニア:" +17480 print "  エリア内を移動できる。":print +17490 waitvb 30:print " ウェーブキヤノン:" +17500 print "  エリア内のすべての敵を同時攻撃":print +17510 waitvb 30:print " 反応弾頭ミサイル:" +17520 print "  敵艦も小惑星も一撃で粉砕する" +17590 d=wait +17600 cls +17610 locate 8,8:print "それでは健闘を祈る!" +17690 d=wait +17700 cls +17710 locate 5,8:print "艦長! WITCH号、出港します!" +17790 d=wait +17900 return + +18000 'GOOD ENDING +18010 cls:print +18020 waitvb 75:print " 作戦開始後";D;"日":print +18030 waitvb 75:print " ";H;"隻の戦艦を失った":print +18032 waitvb 75:print " ゴブリン帝国は、全面降伏した":print +18035 waitvb 75:print " 宇宙の平和は守られたのだ":print +18040 waitvb 75:print " WITCH号ならびに艦長の活躍をたたえ":print +18050 waitvb 75:print " 全人類から感謝の言葉をおくる":print +18060 waitvb 75:locate 10,14:print "ありがとう!" +18070 waitvb 75:locate 10,16:print "CONGRATURATIONS!"; +18080 d=wait +18090 end + +locate 10,10:print "●●●●"; + +19000 'BAD ENDING +19010 cls:print +19020 waitvb 75:print " 作戦開始後";D;"日":print +19030 waitvb 75:print " WITCH号、宇宙の藻屑と消える":print +19040 waitvb 75:print " この日、地球連邦政府は、ゴブリン帝国に降伏":print +19050 waitvb 75:print " 地球人はゴブリン帝国の奴隷となった":print +19060 waitvb 75:locate 17,16:print "GAME OVER!"; +19080 d=wait +19090 end +20000 ' clear message +20010 for i=11 to 15:locate 1,i +20020 print "                          "; +20030 next +20040 return +21000 ' 数値入力 +21010 locate X,Y+0:print "┏━━━━┓"; +21020 locate X,Y+1:print "┃    ┃"; +21030 locate X,Y+2:print "┃0000┃"; +21040 locate X,Y+3:print "┃    ┃"; +21050 locate X,Y+4:print "┗━━━━┛"; +21100 for i=0 to 3:@(W+i)=0:next +21110 v=3 '桁位置 +21200 locate X+v+1,Y+1:print "↑"; +21210 locate X+v+1,Y+3:print "↓"; +21220 for i=0 to 3:locate X+i+1,Y+2:print @(W+i);:next +21300 s=wait +21310 locate X+v+1,Y+1:print " "; +21320 locate X+v+1,Y+3:print " "; +21330 if s and scan_x3 then @(W+v)=@(W+v)-1:if @(W+v)<0 then @(W+v)=9 +21340 if s and scan_x1 then @(W+v)=@(W+v)+1:if @(W+v)>9 then @(W+v)=0 +21350 if s and scan_x2 then v=v+1:if v>3 then v=0 +21360 if s and scan_x4 then v=v-1:if v<0 then v=3 +21365 if s and scan_a then goto 21400 +21370 if s and scan_b then Z=-1:return +21380 goto 21200 +21400 Z=@(W+0)*1000+@(W+1)*100+@(W+2)*10+@(W+3) +21410 return + +22000 ' 疑似三角関数(Y=sin(X)) Y=-100...100 X=0-360 +22010 X=X/5 +22020 if X<=18 then gosub 22100:return +22030 if X<=36 then X=36-X:gosub 22100:return +22040 if X<=54 then X=X-36:gosub 22100:Y=-Y:return +22050 if X<=72 then X=72-X:gosub 22100:Y=-Y:return +22060 X=X-72:goto 22020 +22100 if X=0 then Y=0 +22110 if X=1 then Y=8 +22120 if X=2 then Y=17 +22130 if X=3 then Y=25 +22140 if X=4 then Y=34 +22150 if X=5 then Y=42 +22160 if X=6 then Y=49 +22170 if X=7 then Y=57 +22180 if X=8 then Y=64 +22190 if X=9 then Y=70 +22200 if X=10 then Y=76 +22210 if X=11 then Y=81 +22220 if X=12 then Y=86 +22230 if X=13 then Y=90 +22240 if X=14 then Y=93 +22250 if X=15 then Y=96 +22260 if X=16 then Y=98 +22270 if X=17 then Y=99 +22280 if X=18 then Y=99 +22290 return +23000 ' 疑似三角関数(cos) +23010 X=X+90:gosub 22000:return +24000 ' 爆発アニメーション +24005 locate 2+X,2+Y:print "・";:waitvb 30 +24010 locate 2+X,2+Y:print "●";:waitvb 30 +24020 locate 2+X,2+Y:print "※";:waitvb 30 +24030 locate 2+X,2+Y:print " "; +24040 d=wait +24090 return +25000 '******ステータス表示更新***** +25010 locate 11,3:print "       "; +25020 locate 14,3:print E; +25030 locate 11,5:print "       "; +25040 locate 14,5:print M; +25050 locate 11,7:print "       "; +25060 locate 14,7:print L; +25070 locate 11,9:print "       "; +25080 locate 14,9:print D; +25090 return +26000 ' エリア内残り敵戦艦を数えてYに返す +26010 Y=0 +26020 for y=0 to 7:for x=0 to 7 +26030 if @(A+x+y*8)>0 then Y=Y+1 +26040 next:next +26090 return + +cls:print"Loading Completed" diff --git a/vc15_rt.asm b/vc15_rt.asm new file mode 100644 index 0000000..65af3fb --- /dev/null +++ b/vc15_rt.asm @@ -0,0 +1,310 @@ +;*** +;vc15_rt.asm: Wonder Witch Start-up code for Visual C++ 1.5x +; + +SRAM_SEG equ 1000h + +MAXPATHLEN equ 64 + +INT_EXIT equ 10h +INT_DISP equ 12h +INT_TEXT equ 13h + +DISPLAY_CONTROL equ 00h +SPRITE_SET_RANGE equ 0bh +SCREEN_SET_SCROLL equ 13h +SCREEN2_SET_WINDOW equ 15h +SPRITE_SET_WINDOW equ 17h +SCREEN_SET_VRAM equ 21h +SPRITE_SET_VRAM equ 22h + +TEXT_SCREEN_INIT equ 00h +TEXT_SET_MODE equ 02h +TEXT_SET_SCREEN equ 0eh + +TEXT_MODE_ANK equ 0 +TEXT_MODE_ANK_SJIS equ 1 +TEXT_MODE_SJIS equ 2 + +SCREEN1 equ 0 +SCREEN2 equ 1 + +DCM_SCR1 equ 1 +DCM_SCR2 equ 2 + +V_SPRITE_START equ 0 +V_SPRITE_COUNT equ 0 + +ifdef DISPLAY_MODE_JAPANESE1 +V_DISPLAY_CONTROL equ DCM_SCR2 +V_TEXT_SCREEN equ SCREEN2 +V_TEXT_MODE equ TEXT_MODE_ANK_SJIS +V_SCREEN1_VRAM equ 3 ; duplicated with screen2 +V_SCREEN2_VRAM equ 3 +V_SPRITE_VRAM equ 11 +V_STACK_TOP equ 01600h +endif + +ifdef DISPLAY_MODE_JAPANESE2 +V_DISPLAY_CONTROL equ DCM_SCR1 + DCM_SCR2 +V_TEXT_SCREEN equ SCREEN2 +V_TEXT_MODE equ TEXT_MODE_ANK_SJIS +V_SCREEN1_VRAM equ 2 +V_SCREEN2_VRAM equ 3 +V_SPRITE_VRAM equ 7 +V_STACK_TOP equ 00e00h +endif + +ifdef DISPLAY_MODE_ASCII1 +V_DISPLAY_CONTROL equ DCM_SCR2 +V_TEXT_SCREEN equ SCREEN2 +V_TEXT_MODE equ TEXT_MODE_ANK +V_SCREEN1_VRAM equ 6 ; duplicated with screen2 +V_SCREEN2_VRAM equ 6 +V_SPRITE_VRAM equ 23 +V_STACK_TOP equ 02e00h +endif + +ifdef DISPLAY_MODE_ASCII2 +V_DISPLAY_CONTROL equ DCM_SCR1 + DCM_SCR2 +V_TEXT_SCREEN equ SCREEN2 +V_TEXT_MODE equ TEXT_MODE_ANK +V_SCREEN1_VRAM equ 6 +V_SCREEN2_VRAM equ 5 +V_SPRITE_VRAM equ 19 +V_STACK_TOP equ 02600h +endif + +_TEXT segment byte public 'CODE' +_TEXT ends + +TEXT segment byte public 'CODE' +TEXT ends + +_DATA segment para public 'DATA' +dseg_start proc far +dseg_start endp +_DATA ends + +DATA segment para public 'DATA' +DATA ends + +CONST segment para public 'CONST' +CONST ends + +_BSS segment word public 'BSS' +bss_start proc far +bss_start endp +_BSS ends + +BSS segment word public 'BSS' +BSS ends + +c_common segment word public 'BSS' +c_common ends + +_HEAP segment para public 'HEAP' +heap_start proc far +heap_start endp +_HEAP ends + +CGROUP group _TEXT, TEXT +DGROUP group _DATA, DATA, CONST, _BSS, BSS, c_common, _HEAP + + assume cs:CGROUP, ds:DGROUP, es:DGROUP + +_TEXT segment byte public 'CODE' + extrn _main :near + public _load0 + public _run0 + public _exit0 + +_load0 proc far + push ds + + push di + push si + push cx + push bx + +; calcurate initialized data size + mov cx, offset DGROUP:bss_start + shr cx, 1 ; word alignmented + +; copy initialized data into user ds + mov ax, cs + sub ax, CGROUP +; add ax, seg dseg_start + add ax, DGROUP + mov ds, ax + mov ax, SRAM_SEG + mov es, ax + mov si, offset DGROUP:dseg_start + mov di, si + rep movsw + +; clear bss + mov cx, offset DGROUP:heap_start + push cx + mov di, offset DGROUP:bss_start + sub cx, di + shr cx, 1 + xor ax, ax + rep stosw + +; calcurate heap start position +; set argv starting position at heap start + pop es:[__argv] + + mov dx, cs + mov ax, offset _run0 + + pop bx + pop cx + pop si + pop di + + pop ds + ret +_load0 endp + +_run0 proc far ;C, argc :word, argv :near ptr + push bp + mov bp,sp + push ds + mov dx, SRAM_SEG + mov es, dx + mov ds, dx +; mov ax, sp +; mov word ptr ds:[__sp], ax +; mov ax, ss +; mov word ptr ds:[__sp + 2], ax + +;; setup SP according to the display modes + +;; display_control(0); + mov bx, 0 + mov ah, DISPLAY_CONTROL + int INT_DISP + +;; screen_set_scroll(SCREEN1, 0, 0); + mov bx, 00000h + mov al, SCREEN1 + mov ah, SCREEN_SET_SCROLL + int INT_DISP + +;; screen_set_scroll(SCREEN2, 0, 0); + mov bx, 00000h + mov al, SCREEN2 + mov ah, SCREEN_SET_SCROLL + int INT_DISP + +;; screen2_set_window(0, 0, 255, 255) + mov cx, 0ffffh + mov bx, 00000h + mov ah, SCREEN2_SET_WINDOW + int INT_DISP + +;; sprite_set_window(0, 0, 255, 255) + mov cx, 0ffffh + mov bx, 00000h + mov ah, SPRITE_SET_WINDOW + int INT_DISP + +;; text_set_screen(V_TEXT_SCREEN); + mov al, V_TEXT_SCREEN + mov ah, TEXT_SET_SCREEN + int INT_TEXT + +;; text_set_mode(V_TEXT_MODE); + mov bx, V_TEXT_MODE + mov ah, TEXT_SET_MODE + int INT_TEXT + +;; screen_set_vram(SCREEN1, V_SCREEN1_VRAM) + mov bx, V_SCREEN1_VRAM + mov al, SCREEN1 + mov ah, SCREEN_SET_VRAM + int INT_DISP + +;; screen_set_vram(SCREEN2, V_SCREEN2_VRAM) + mov bx, V_SCREEN2_VRAM + mov al, SCREEN2 + mov ah, SCREEN_SET_VRAM + int INT_DISP + +;; sprite_set_vram(SCREEN2, V_SCREEN2_VRAM) + mov bx, V_SPRITE_VRAM + mov ah, SPRITE_SET_VRAM + int INT_DISP + +;; sprite_set_range(V_SPRITE_START, V_SPRITE_COUNT) + mov cx, V_SPRITE_COUNT + mov bx, V_SPRITE_START + mov ah, SPRITE_SET_RANGE + int INT_DISP + +;; display_control(V_DISPLAY_CONTROL); + mov bx, V_DISPLAY_CONTROL + mov ah, DISPLAY_CONTROL + int INT_DISP + + MOV CX, [BP + 8] ; for argv ; mov bx, argc + MOV BX, [BP + 6] ; for argc ; mov cx, argv + + mov ax, V_STACK_TOP + mov sp, ax + push cx ; argv + push bx ; argc + call _main +_exit00: +_exit0: + int INT_EXIT + ;mov sp,bp + ;pop bp + ;ret +_run0 endp + +;_exit0: +; mov ax, SRAM_SEG +; mov es, ax +; les ax, dword ptr es:[__sp] +; mov sp, ax +; mov ax, es +; mov ss, ax +; jmp _exit00 +_TEXT ends + +_DATA segment para public 'DATA' + +public __acrtused ; trick to force in startup + __acrtused = 9876h ; funny value not easily matched in SYMDEB + + public __id + public __pid + public __ppid + public __pcbid + public __ppcbid + public __ilib + public __proc + public __cwfs + public __currentdir + public __argv + public __heap +;dseg_start: +__id db 'TCC', 0 +__pid dw ? +__ppid dw ? +__pcbid dw ? +__ppcbid dw ? +__ilib dd ? +__proc dd ? +__cwfs dd ? +__currentdir db MAXPATHLEN dup (?) +__argv dw ? +__resource dd ? +__heap dw ? +_DATA ends + + end + diff --git a/win32text.c b/win32text.c index 67dee98..c233c57 100644 --- a/win32text.c +++ b/win32text.c @@ -9,7 +9,8 @@ #define SCREEN_SIZE_Y (144/8) static WORD screen[SCREEN_SIZE_X][SCREEN_SIZE_Y]; -static WORD lastChar; +//static WORD lastChar; +static UINT lastVKey; static HWND hwnd; @@ -22,6 +23,7 @@ static void wmPaint( HWND hWnd, HDC hdc ) GetClientRect( hWnd, &rect ); + SelectObject( hdc, GetStockObject( SYSTEM_FIXED_FONT ) ); GetTextMetrics( hdc, &tm ); xArea = SCREEN_SIZE_X * tm.tmMaxCharWidth; @@ -48,11 +50,19 @@ static void wmPaint( HWND hWnd, HDC hdc ) rectDraw.top+y*tm.tmHeight, str, 2 ); } else { - str[0] = (BYTE)val; - TextOut( hdc, - rectDraw.left+x*tm.tmMaxCharWidth, - rectDraw.top+y*tm.tmHeight, - str, 1 ); + static char table[] = " !”#$%&’()*+,−./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[¥]^_`abcdefghijklmnopqrstuvwxyz{|} ̄"; + if( val >= 0x20 && val <= 0x7e ) { + TextOut( hdc, + rectDraw.left+x*tm.tmMaxCharWidth, + rectDraw.top+y*tm.tmHeight, + &table[(val-0x20)*2], 2 ); + } else { + str[0] = (BYTE)val; + TextOut( hdc, + rectDraw.left+x*tm.tmMaxCharWidth, + rectDraw.top+y*tm.tmHeight, + str, 1 ); + } } } } @@ -70,10 +80,14 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) EndPaint(hWnd, &ps); break; - case WM_CHAR: - lastChar = (WORD)wParam; + case WM_KEYDOWN: + lastVKey = (WORD)wParam; break; + //case WM_CHAR: + // lastChar = (WORD)wParam; + // break; + case WM_CLOSE: return 0; // 閉じちゃ駄目 @@ -166,7 +180,8 @@ int createText() DWORD dwThreadId, dwThrdParam = 1; HANDLE hThread; - lastChar = 0; + //lastChar = 0; + lastVKey = 0; hThread = CreateThread( NULL, // no security attributes 0, // use default stack size @@ -179,42 +194,37 @@ int createText() unsigned short win32_wait() { - WORD t; + UINT t; while( TRUE ) { // 以下の2行は本当はマルチスレッド的にNGなんだけど // テスト用環境だから大目に見る - t = lastChar; - lastChar = 0; + t = lastVKey; + lastVKey = 0; switch( t ) { - case 'p': case 'P': return 0x02; // START BUTTON - case ' ': + case VK_SPACE: return 0x04; //KEYWORD_SCAN_A; - case 0x1b: + case VK_ESCAPE: return 0x08; //KEYWORD_SCAN_B; - case 'e': + case VK_UP: case 'E': return 0x10; //KEYWORD_SCAN_X1; - case 'd': + case VK_RIGHT: case 'D': return 0x20; //KEYWORD_SCAN_X2; - case 'x': + case VK_DOWN: case 'X': return 0x40; //KEYWORD_SCAN_X3; - case 's': + case VK_LEFT: case 'S': return 0x80; //KEYWORD_SCAN_X4; - case 't': case 'T': return 0x100; //KEYWORD_SCAN_Y1; - case 'g': case 'G': return 0x200; //KEYWORD_SCAN_Y2; - case 'v': case 'V': return 0x400; //KEYWORD_SCAN_Y3; - case 'f': case 'F': return 0x800; //KEYWORD_SCAN_Y4; } diff --git a/wonbe.c b/wonbe.c index 916428b..6ca8474 100644 --- a/wonbe.c +++ b/wonbe.c @@ -7,18 +7,22 @@ #include #include #include +#ifdef WIN32 +#include +#endif #ifdef WW #include #include #include #include +#define assert(x) #endif #include "keywords.h" #ifdef WIN32 #include "win32text.h" #endif -char myVersion[] = "0.03"; +char myVersion[] = "0.04"; #ifdef WW #define MEMMOVE mymemmove @@ -106,7 +110,7 @@ void consoleInput( BYTE * buf, WORD len ) if( ch == 0x08 ) { /* BS */ if( cursor > 0 ) { cursor--; - comm_send_char( ch ); + comm_send_char( (unsigned char)ch ); continue; } } @@ -119,7 +123,7 @@ inputAsChar: if( cursor < len-1 ) { buf[cursor] = ch; cursor++; - comm_send_char( ch ); + comm_send_char( (unsigned char)ch ); } } } @@ -134,39 +138,91 @@ typedef struct { const BYTE * name; } KEYWORDITEM; -KEYWORDITEM keywords[] = { - { KEYWORD_IF,"if" }, - { KEYWORD_PRINT,"print" }, - { KEYWORD_LOCATE,"locate" }, +KEYWORDITEM keywordsA[] = { + { KEYWORD_AND,"and" }, + { KEYWORD_ABS,"abs" }, + { 0,NULL } +}; + +KEYWORDITEM keywordsB[] = { + { KEYWORD_BREAK,"break" }, + { 0,NULL } +}; + +KEYWORDITEM keywordsC[] = { + { KEYWORD_CHR,"chr" }, { KEYWORD_CLS,"cls" }, + { KEYWORD_CONT,"cont" }, + { 0,NULL } +}; + +KEYWORDITEM keywordsD[] = { + { KEYWORD_DEBUG,"debug" }, + { 0,NULL } +}; + +KEYWORDITEM keywordsE[] = { + { KEYWORD_END,"end" }, + { KEYWORD_EXIT,"exit" }, + { 0,NULL } +}; + +KEYWORDITEM keywordsF[] = { + { KEYWORD_FOR,"for" }, + { KEYWORD_FILES,"files" }, + { 0,NULL } +}; + +KEYWORDITEM keywordsG[] = { { KEYWORD_GOTO,"goto" }, { KEYWORD_GOSUB,"gosub" }, - { KEYWORD_RETURN,"return" }, - { KEYWORD_FOR,"for" }, - { KEYWORD_NEXT,"next" }, - { KEYWORD_END,"end" }, - { KEYWORD_BREAK,"break" }, - { KEYWORD_REM,"rem" }, - { KEYWORD_NEW,"new" }, + { 0,NULL } +}; + +KEYWORDITEM keywordsI[] = { + { KEYWORD_IF,"if" }, + { 0,NULL } +}; + +KEYWORDITEM keywordsL[] = { + { KEYWORD_LOCATE,"locate" }, { KEYWORD_LIST,"list" }, - { KEYWORD_RUN,"run" }, - { KEYWORD_CONT,"cont" }, - { KEYWORD_SAVE,"save" }, { KEYWORD_LOAD,"load" }, + { 0,NULL } +}; + +KEYWORDITEM keywordsM[] = { { KEYWORD_MERGE,"merge" }, - { KEYWORD_RANDOMIZE,"randomize" }, - { KEYWORD_EXIT,"exit" }, - { KEYWORD_DEBUG,"debug" }, - { KEYWORD_WAITVB,"waitvb" }, - { KEYWORD_FILES,"files" }, - { KEYWORD_AND,"and" }, - { KEYWORD_OR,"or" }, - { KEYWORD_XOR,"xor" }, + { 0,NULL } +}; +KEYWORDITEM keywordsN[] = { + { KEYWORD_NEXT,"next" }, { KEYWORD_NOT,"not" }, - { KEYWORD_WAIT,"wait" }, + { KEYWORD_NEW,"new" }, + { 0,NULL } +}; + +KEYWORDITEM keywordsO[] = { + { KEYWORD_OR,"or" }, + { 0,NULL } +}; + +KEYWORDITEM keywordsP[] = { + { KEYWORD_PRINT,"print" }, + { 0,NULL } +}; + +KEYWORDITEM keywordsR[] = { + { KEYWORD_REM,"rem" }, + { KEYWORD_RETURN,"return" }, { KEYWORD_RND,"rnd" }, - { KEYWORD_ABS,"abs" }, - { KEYWORD_TICK,"tick" }, + { KEYWORD_RUN,"run" }, + { KEYWORD_RANDOMIZE,"randomize" }, + { 0,NULL } +}; + +KEYWORDITEM keywordsS[] = { + { KEYWORD_STEP,"step" }, { KEYWORD_SCAN_A,"scan_a" }, { KEYWORD_SCAN_B,"scan_b" }, { KEYWORD_SCAN_X1,"scan_x1" }, @@ -178,12 +234,36 @@ KEYWORDITEM keywords[] = { { KEYWORD_SCAN_Y3,"scan_y3" }, { KEYWORD_SCAN_Y4,"scan_y4" }, { KEYWORD_SCAN,"scan" }, /* scanはscna_Xより後になければならない */ - { KEYWORD_THEN,"then" }, - { KEYWORD_CHR,"chr" }, - { KEYWORD_TO,"to" }, - { KEYWORD_STEP,"step" }, + { KEYWORD_SAVE,"save" }, { 0,NULL } }; +KEYWORDITEM keywordsT[] = { + { KEYWORD_THEN,"then" }, + { KEYWORD_TO,"to" }, + { KEYWORD_TICK,"tick" }, + { 0,NULL } +}; + +KEYWORDITEM keywordsW[] = { + { KEYWORD_WAITVB,"waitvb" }, + { KEYWORD_WAIT,"wait" }, // waitはwaitvbより後になければならない + { 0,NULL } +}; + +KEYWORDITEM keywordsX[] = { + { KEYWORD_XOR,"xor" }, + { 0,NULL } +}; + +KEYWORDITEM * keywordsIndex[26] = { + keywordsA, keywordsB, keywordsC, keywordsD, + keywordsE, keywordsF, keywordsG, NULL, + keywordsI, NULL, NULL, keywordsL, + keywordsM, keywordsN, keywordsO, keywordsP, + NULL, keywordsR, keywordsS, keywordsT, + NULL, NULL, keywordsW, keywordsX, + NULL, NULL +}; /* インタラクティブモード時の1行バッファ */ BYTE waRawLine[LINE_SIZE]; @@ -254,6 +334,9 @@ int requestNextAction; /* #define REQUEST_MERGE_FILE 7 /* REQUEST_RUN_LINENUMBERで実行開始をリクエストする行番号 */ WORD runLineNumber; +// 編集機能が追加専用モードであることを示す +// REQUEST_RUN_FILE or REQUEST_LOAD_FILE経由で処理するときだけTRUEとなる +BOOL appendMode = FALSE; /* エラー発生 */ void syntaxError() @@ -377,6 +460,14 @@ BYTE * skipToEOL( BYTE * p ) } } +BYTE * skipToNextLine( BYTE * p ) +{ + return skipToEOL( p+4 ); // +4は行番号2バイト行長さ2バイト +} + +#if 1 +#define mytolower(ch) ((ch >= 'A' && ch <= 'Z')? ch - 'A' + 'a' : ch) +#else BYTE mytolower( BYTE ch ) { if( ch >= 'A' && ch <= 'Z' ) { @@ -384,6 +475,7 @@ BYTE mytolower( BYTE ch ) } return ch; } +#endif /* シフトJISの1バイト目かどうか判断。マクロなので副作用に注意 */ #define IsDBCSLeadByte(ch) ((ch >= 0x81 && ch <= 0x9f) || (ch >= 0xe0 && ch <= 0xfc)) @@ -407,7 +499,7 @@ void processLineHeader() { if( !bInteractive ) { currentLineNumber = *((WORD *)executionPointer); - executionPointer += 2; + executionPointer += 4; // +4は行番号2バイト行長さ2バイト } else { currentLineNumber = 0; } @@ -427,9 +519,7 @@ BYTE * getLineReferenceFromLineNumber( WORD lineNumber ) if( lineNumber == t ) { return p; } - p += 2; - p = skipToEOL( p ); - p++; + p += *((WORD *)(p+2)); } } @@ -446,9 +536,7 @@ BYTE * getInsertionPointFromLineNumber( WORD lineNumber ) if( lineNumber <= t ) { return p; } - p += 2; - p = skipToEOL( p ); - p++; + p += *((WORD *)(p+2)); } } @@ -519,7 +607,7 @@ void ptextTab() xCursor = (xCursor+TABSTOP) / TABSTOP * TABSTOP; } -void ptextString( const BYTE * msg ) +void ptextString( const BYTE FAR * msg ) { while( TRUE ) { WORD ch; @@ -591,7 +679,7 @@ BOOL sourceDump( FILE FAR * fp, WORD from, WORD to ) lineNumber = *((WORD*)p); if( lineNumber == 0 ) break; if( lineNumber > to ) break; - p += 2; + p += 4; b = commonPrint(fp,"%d",lineNumber); if( b == FALSE ) return FALSE; while( TRUE ) { @@ -626,29 +714,38 @@ BOOL sourceDump( FILE FAR * fp, WORD from, WORD to ) p++; } } else if( *p >= 0x80 ) { - KEYWORDITEM * k = keywords; - while( TRUE ) { - if( k->id == 0 ) { - b = commonPrint(fp,"[?%x?]", *p ); - if( b == FALSE ) return FALSE; - p++; - break; - } - if( k->id == *p ) { - b = commonPrint(fp, k->name ); - if( b == FALSE ) return FALSE; - p++; - if( k->id == KEYWORD_REM ) { /* コメントのあとはそのまま行末まで転送 */ - while( TRUE ) { - if( *p == EOL ) break; - b = commonPrint(fp,"%c",*p); - if( b == FALSE ) return FALSE; - p++; + int i; + BOOL found; + found = FALSE; + for( i=0; i<26; i++ ) { + KEYWORDITEM * k; + if( found ) break; + k = keywordsIndex[i]; + if( k == NULL ) continue; + while( TRUE ) { + if( k->id == 0 ) break; + if( k->id == *p ) { + b = commonPrint(fp, k->name ); + if( b == FALSE ) return FALSE; + p++; + if( k->id == KEYWORD_REM ) { /* コメントのあとはそのまま行末まで転送 */ + while( TRUE ) { + if( *p == EOL ) break; + b = commonPrint(fp,"%c",*p); + if( b == FALSE ) return FALSE; + p++; + } } + found = TRUE; + break; } - break; + k++; } - k++; + } + if( !found ) { + b = commonPrint(fp,"[?%x?]", *p ); + if( b == FALSE ) return FALSE; + p++; } } else { b = commonPrint(fp,"%c",*p); @@ -1516,13 +1613,21 @@ void editLine() { WORD wishLineNumber; BYTE ch, * p, * target; - /* トリックに注意! */ - /* 行頭の整数を、行番号に変換するには結果的に先頭の0x01を取り去るだけで良い */ - MEMMOVE( waCoockedLine, waCoockedLine+1, LINE_SIZE-1 ); - /* トリック終わり。この時点でwsCoockedLineは、プログラム内部表現の形式に一致している */ - wishLineNumber = *((WORD*)waCoockedLine); - p = waCoockedLine+2; - target = getLineReferenceFromLineNumber( wishLineNumber ); + WORD lineNumber; + + // プログラム領域に行を格納する場合は + // 先頭に2バイトの行番号と2バイトの行長さの情報が格納される + // 一方、中間言語翻訳の結果は先頭に0x01で始まる10進整数が行番号として入っている + // このギャップを転送時に解消しなければならない + + // ここに来ているということは、waCoockedLine[0]が0x01つまり10進整数である // + assert( waCoockedLine[0] == 0x01 ); + wishLineNumber = *((WORD*)&waCoockedLine[1]); + p = waCoockedLine+3; + //target = getLineReferenceFromLineNumber( wishLineNumber ); + target = getInsertionPointFromLineNumber( wishLineNumber ); + lineNumber = *((WORD*)target); + while( TRUE ) { ch = *p++; if( ch != ' ' && ch != '\t' ) break; @@ -1531,37 +1636,31 @@ void editLine() WORD delta; BYTE * from; /* removing the line */ - if( target == NULL ) { + if( lineNumber == 0 || lineNumber != wishLineNumber ) { lineNumberNotFound( wishLineNumber ); return; } - from = skipToEOL(target)+1; + from = skipToNextLine(target); delta = from-target; MEMMOVE( target, from, (WORD)(dataTop-(from-wa)) ); dataTop -= delta; - /*clearRuntimeInfo();*/ } else { - WORD len; - len = skipToEOL(waCoockedLine+2)-waCoockedLine+1; - if( target == NULL ) { + WORD len; // プログラム領域上に収めるときのサイズ + len = skipToEOL(p)-waCoockedLine-1+2+1; //-1は0x01の分。+2は長さ情報。+1はEOL + if( lineNumber == 0 || lineNumber != wishLineNumber ) { /* insert new line */ - /*const BYTE * to;*/ if( dataTop + len >= WORKAREA_SIZE ) { outOfMemory(); return; } - target = getInsertionPointFromLineNumber( wishLineNumber ); - /* to = skipToEOL(target)+1; */ MEMMOVE( target+len, target, (WORD)(dataTop-(target-wa)) ); - MEMMOVE( target, waCoockedLine, len ); dataTop += len; - /*clearRuntimeInfo();*/ } else { /* replace line */ WORD lost; BYTE * nextline; int delta; - nextline = skipToEOL(target)+1; + nextline = skipToNextLine(target)+1; lost = nextline-target; delta = len-lost; if( dataTop + delta >= WORKAREA_SIZE ) { @@ -1569,13 +1668,42 @@ void editLine() return; } MEMMOVE( nextline+delta, nextline, (WORD)(dataTop-(nextline-wa)) ); - MEMMOVE( target, waCoockedLine, len ); dataTop += delta; - /*clearRuntimeInfo();*/ } + // まず行番号をコピーする + *((WORD*)target) = *((WORD*)&waCoockedLine[1]); + // 行の長さを収める + *((WORD*)(target+2)) = len; + // 残りをコピーする + MEMMOVE( target+4, waCoockedLine+3, (WORD)(len-4) ); } } +/* 追加専門の行エディタ */ +void appendLine() +{ + BYTE * target; + WORD len; // プログラム領域上に収めるときのサイズ + len = skipToEOL(waCoockedLine+3)-waCoockedLine-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+2)) = len; + // 残りをコピーする + MEMMOVE( target+4, waCoockedLine+3, (WORD)(len-4) ); + dataTop += len; + wa[dataTop-5] = 0; + wa[dataTop-4] = 0; + wa[dataTop-3] = 0; + wa[dataTop-2] = 0; + wa[dataTop-1] = EOL; +} + /* 中間言語に翻訳する */ BOOL convertInternalCode( BYTE * waCoockedLine, const BYTE * waRawLine ) { @@ -1583,6 +1711,8 @@ BOOL convertInternalCode( BYTE * waCoockedLine, const BYTE * waRawLine ) BYTE * dst = waCoockedLine; while( TRUE ) { if( *src == '\0' ) break; + if( *src == '\n' ) break; + if( *src == '\r' ) break; if( *src == ' ' || *src == '\t' ) { *dst++ = *src++; } else if( *src < 0x20 ) { @@ -1657,7 +1787,11 @@ BOOL convertInternalCode( BYTE * waCoockedLine, const BYTE * waRawLine ) BYTE next = *(src+1); if( (next >= 'a' && next <= 'z') || (next >= 'A' && next <= 'Z') ) { WORD id; - KEYWORDITEM * p = keywords; + KEYWORDITEM * p = keywordsIndex[mytolower(*src)-'a']; + if( p == NULL ) { + syntaxError(); + return FALSE; + } id = 0; while( TRUE ) { const BYTE * ps, * pd; @@ -1814,18 +1948,8 @@ void interactiveMain( FILE FAR * fp ) consoleInput( waRawLine, LINE_SIZE ); } else { char FAR * r; - char * p; r = fgets( waRawLine, LINE_SIZE, fp ); if( r == NULL ) break; - p = waRawLine; - while( TRUE ) { - if( *p == '\0' ) break; - if( *p == '\n' || *p == '\r') { - *p = '\0'; - break; - } - p++; - } } #ifdef WW if( fp == NULL ) { @@ -1841,7 +1965,11 @@ void interactiveMain( FILE FAR * fp ) /* 数値で開始されているか? */ if( waCoockedLine[0] == 0x01 ) { /* 行エディタを呼び出す */ - editLine(); + if( appendMode ) { + appendLine(); + } else { + editLine(); + } if( fp == NULL ) { clearRuntimeInfo(); } @@ -1879,8 +2007,10 @@ void do_new() codeTop = 0; wa[0] = 0; wa[1] = 0; - wa[2] = EOL; - dataTop = 3; + wa[2] = 0; + wa[3] = 0; + wa[4] = EOL; + dataTop = 5; } BOOL do_merge( const BYTE * filename ) @@ -1912,14 +2042,18 @@ void superMain() break; case REQUEST_RUN_FILE: do_new(); + appendMode=TRUE; b = do_merge( waRawLine ); + appendMode=FALSE; if( b ) { do_run( 0 ); } break; case REQUEST_LOAD_FILE: do_new(); + appendMode=TRUE; do_merge( waRawLine ); + appendMode=FALSE; break; case REQUEST_MERGE_FILE: do_merge( waRawLine ); @@ -1945,12 +2079,10 @@ void superMain() BOOL entranceUI() { #define MAX_ENT 15 - /* この関数内のstaticはTurbo-C 2.0のSS!=DS問題を回避するために必要なもの */ - static int i; - struct stat statbuf; - static char names[MAX_ENT][MAXFNAME]; - static int nent; - static int c, select; + int i; + struct stat statbuf[MAX_ENT]; + int nent; + int c, select; ptextCLS(); ptextString( "ワンべぇ V" ); @@ -1964,37 +2096,20 @@ BOOL entranceUI() for (i = 0; i < nent; i++) { int result; if( c >= MAX_ENT ) break; - result = getent(NULL, i, &statbuf); + result = getent(NULL, i, &statbuf[c]); if (result == E_FS_SUCCESS) { - if (statbuf.count != -1) { - /* Freya OSのバグ? 回避コード */ - { - static int p; - int q; - p = 0; - q = 0; - waRawLine[p++] = statbuf.info[q++]; - waRawLine[p++] = statbuf.info[q++]; - while( TRUE ) { - if( statbuf.info[q] == '\0' ) break; - waRawLine[p++] = statbuf.info[q++]; + if (statbuf[c].count != -1) { + char FAR * p; + int l; + p = statbuf[c].name; + l = strlen(p); + if( l >= 3 ) { + if( p[l-3] == '.' && p[l-2] == 'w' && p[l-1] == 'b' ) { + ptextLocate(1,c+2); + ptextString( statbuf[c].info ); + c++; } - waRawLine[p++] = '\0'; - ptextLocate(1,c+2); - ptextString( waRawLine ); } - { - static int r; - int q; - q = 0; - r = 0; - while( TRUE ) { - if( statbuf.name[q] == '\0' ) break; - names[c][r++] = statbuf.name[q++]; - } - names[c][r] = '\0'; - } - c++; } } } @@ -2006,34 +2121,39 @@ BOOL entranceUI() ptextLocate(0,i+2); ptextString( " " ); } - ptextLocate(0,select+2); - ptextString( "→" ); + if( c > 0 ) { + ptextLocate(0,select+2); + ptextString( "→" ); + } key = key_wait(); - /* START */ + /* START button */ if( key & 0x02 ) return FALSE; /* 中止 */ - /* A */ - if( key & 0x04 ) { - strcpy( waRawLine, names[select] ); - requestNextAction = REQUEST_RUN_FILE; - runtimeOnly = TRUE; - return TRUE; - } - /* B */ + /* B button */ if( key & 0x08 ) return FALSE; /* 中止 */ - /* X1 or Y1 */ - if( (key & 0x10) != 0 || (key & 0x100) != 0 ) { - select = select-1; - if( select < 0 ) { - select = c-1; - } - } - /* X3 or Y3 */ - if( (key & 0x40) != 0 || (key & 0x400) != 0 ) { - select = select+1; - if( select >= c ) { - select = 0; + if( c > 0 ) { + /* A button */ + if( key & 0x04 ) { + strcpy( waRawLine, statbuf[select].name ); + requestNextAction = REQUEST_RUN_FILE; + runtimeOnly = TRUE; + return TRUE; + } + /* X1 or Y1 */ + if( (key & 0x10) != 0 || (key & 0x100) != 0 ) { + select = select-1; + if( select < 0 ) { + select = c-1; + } + } + /* X3 or Y3 */ + if( (key & 0x40) != 0 || (key & 0x400) != 0 ) { + select = select+1; + if( select >= c ) { + select = 0; + } } } + /* Y2 button */ if( (key & 0x200) != 0 ) { return TRUE; } diff --git a/wonbe.dsp b/wonbe.dsp index e4b2825..3940a25 100644 --- a/wonbe.dsp +++ b/wonbe.dsp @@ -39,6 +39,7 @@ RSC=rc.exe # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c @@ -62,6 +63,7 @@ LINK32=link.exe # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c @@ -72,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 /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 !ENDIF diff --git a/wonbe.exe b/wonbe.exe index bc30775..80b3fb2 100644 Binary files a/wonbe.exe and b/wonbe.exe differ diff --git a/wonbe.fx b/wonbe.fx index cd0bd9d..61a31df 100644 Binary files a/wonbe.fx and b/wonbe.fx differ diff --git a/wonbe.txt b/wonbe.txt index f4ac7fd..dbcf3a3 100644 --- a/wonbe.txt +++ b/wonbe.txt @@ -1,6 +1,6 @@ ワンべぇ: WONBE, WonderWitch BASIC Environment - 暫定マニュアル Ver 0.03 - 2000年11月7日 + 暫定マニュアル Ver 0.04 + 2000年11月12日 株式会社ピーデー 川俣 晶 Copyright 2000 (c) by Pie Dey Co.Ltd. @@ -203,7 +203,7 @@ tick  システムタイマーのtickを返します。ただし、本来のtick値は符号無し32bit整数であり、ここで得られるのは16bit符号あり整数であることに注意が必要です。はみ出たbitは捨てられます。 ● ファイル保存時の拡張子 - 一応、ワンべぇのソースフィルは、".wb"で終わるファイル名にしておいて下さい。現在エントランスメニューには全ファイルが見えていますが、".wb"で終わるファイル名だけに限定しようかと考えています。 + ワンべぇのソースフィルは、".wb"で終わるファイル名にしておいて下さい。loadなどのコマンドでは拡張子に関係なく読み込めますが、エントランスメニューに表示されるのは".wb"で終わるファイル名だけです。 ● 配布規則  現バージョンは品質が不明のテスト版です。 @@ -221,6 +221,13 @@ tick ● 変更履歴 +2000年11月12日 Ver 0.04 +・13など0x0dを含む行番号を削除しようとするとプログラムが壊れたバグを取った +・処理系をTurbo C2.0からVisual C++ 1.51に変更 +・ロード速度を大幅に改善 +・エントランスメニューは.wbのみ表示 +・サンプルゲームSTAR WITCH(star.wb, star.txt)を添付 + 2000年11月7日 Ver 0.03 ・演算子の優先順位 単項演算子 > */ > +- > 比較演算子 > and,or,xor ・比較演算子成立時の値を1から-1に変更