• R/O
  • SSH
  • HTTPS

コミット

タグ
未設定

よく使われているワード(クリックで追加)

javaandroidc++linuxc#objective-ccocoa誰得qtrubybathyscaphegamephpguiwindowsc翻訳pythonomegattwitterframeworkbtronarduinovb.net計画中(planning stage)directxpreviewertestゲームエンジンdom

BASIC compiler/interpreter for PIC32MX/MZ-80K (suspended)


コミットメタ情報

リビジョン271 (tree)
日時2018-10-15 09:17:26
作者kmorimatsu

ログメッセージ

(メッセージはありません)

変更サマリ

差分

--- mips/branches/zoeaobjective/help.txt (nonexistent)
+++ mips/branches/zoeaobjective/help.txt (revision 271)
@@ -0,0 +1,677 @@
1+<BASIC言語の書式>
2+BASICプログラムの記述は、行番号式、ラベル式、その混合、いずれの方法でも構
3+いません。以下、仕様について述べます。
4+
5+<利用可能な変数型>
6+利用できる変数の型は、32ビット符号付整数(-2147483648 以上 +2147483647 以
7+下)と、文字列型の2種類です。文字列の末端部には0x00が付加されます。
8+
9+A-Zの26個の整数型変数が利用可能です。文字列として扱う場合はA$のように記
10+述します。ただし、A(整数型)とA$(文字列型)を同時に使用することは出来ま
11+せん。
12+
13+整数型の定数は、10進法で記述します。16進法を使う場合、「$1200」のよう
14+に、頭に「$」を付加するか、「0x1200」の様に表記して下さい。
15+
16+文字列型の定数は、「"」で囲って記述してください。「"」を使用する場合は、
17+「CHR$($22)」のように記述することが出来ます。
18+
19+<命令>
20+以下、x, y, z等は整数値を、x$, y$, z$は文字列を、x#, y#, z#は浮動
21+小数点型実数値を指します。xxx, yyy, zzz, www等は任意のステートメントを
22+指します。[ ]は省略可能である事を示します。
23+
24+命令同士を「:」で区切ることにより、一行で複数のコマンドを処理すること
25+が出来ます。
26+
27+BGCOLOR r,g,b
28+ 背景色指定。
29+BREAK
30+ FOR-NEXT, DO-LOOP, WHILE-WENDループから抜け出す。
31+CDATA x[,y[,z[...]]]
32+ データー列を8ビット整数値で指定する。
33+CLEAR
34+ すべての文字列型変数と整数型配列を破棄し、整数値を0とする。また、
35+ PCGの使用をやめ、表示キャラクターをリセットする。
36+CLS
37+ スクリーン消去。
38+COLOR x
39+ テキスト色指定。
40+CONTINUE
41+ FOR-NEXT, DO-LOOP, WHILE-WENDループ中で、以降のコードをスキップす
42+ る。
43+CURSOR x,y
44+ カーソル位置指定。
45+CDATA xxx[,yyy[,zzz[...]]]
46+ データー列を8ビット整数値で指定する。
47+DATA xxx[,yyy[,zzz[...]]]
48+ データー列を整数値もしくは文字列で指定する。
49+DIM xxx [, yyy [, zzz [, ... ]]]
50+ 整数型もしくは浮動小数点型の配列を割り当てる。
51+ xxx,yyy,zzzは、例えば「A(10)」のように記述する。この場合、A(0)から
52+ A(10)までの11個の整数型変数が確保される。浮動小数点型配列の場合は、
53+ 「A#(10)」の様に記述する。多次元配列も、宣言することが出来る。
54+DO WHILE x
55+LOOP
56+ x が0以外の場合、DO文からLOOP文までのステートメントを繰り返し実行する。
57+DO UNTIL x
58+LOOP
59+ x が0の場合、DO文からLOOP文までのステートメントを繰り返し実行する。
60+DO
61+LOOP WHILE x
62+ DO文からLOOP文までのステートメントを実行し、x が0以外の場合、繰り返す。
63+DO
64+LOOP UNTIL x
65+ DO文からLOOP文までのステートメントを実行し、x が0の場合、繰り返す。
66+DRAWCOUNT
67+ DRAWCOUNT値を指定する。DRAWCOUNT値に付いては、DRAWCOUNT()関数を
68+ 参照。
69+END
70+ BASICプログラムを停止する。
71+EXEC x[,y[,z[...]]]
72+ 機械語を実行する。ただし、x,y,zは32ビット整数値。
73+FOR x=yyy TO zzz [ STEP www ]
74+NEXT
75+ yyyで示された計算結果をxに代入し、xの値がzzzになるまで次のNEXT文
76+ までのステートメントを、繰り返し実行する。繰り返しのたび、xの値は
77+ wwwずつ増加する(省略された場合は1ずつ)。「NEXT」の次に何も記述
78+ しないことに注意。
79+GOSUB xxx [, yyy [, zzz [, ... ]]]
80+ 現在の実行位置を記憶し、xxx行目(もしくはラベル)に移動する。yyy, zzz
81+ 等は、サブルーチンに引き継がれる引数(ARGS()関数を参照)。
82+GOTO xxx
83+ xxx行目(もしくはラベル)に移動する。
84+IF xまたはx# THEN yyy [ ELSE zzz ]
85+ xが0以外のとき、yyyを、0のときzzzを実行。yyyおよびzzzは、複数のステート
86+ メントを「:」で挟んで記述可能。
87+IF xまたはx# THEN
88+xxx
89+[ELSEIF yまたはy# THEN
90+yyy]
91+[ELSE
92+zzz]
93+ENDIF
94+ xが0以外の時xxxを、それ以外で且つyが0以外の時(記述された場合)yyyを、
95+ それ以外の場合にzzzを実行。ELSEIFステートメントは、複数記述可。各行で、
96+ THENステートメントの次には何も記入しないことに注意。
97+LABEL xxx
98+ GOTO/GOSUBのジャンプ先を登録する。xxxは、英数字6文字以内の文字列。
99+[LET] x=yyy
100+ yで示された計算結果を、x(整数型変数)に代入する。「LET」は省略可。
101+[LET] x#=yyy
102+ yで示された計算結果を、x(浮動小数点型変数)に代入する。「LET」は省略可。
103+[LET] x$=yyy
104+ yyyで示された文字列(もしくは連結結果;連結演算子は「+」)を、x$に
105+ 代入する。「LET」は省略可。
106+MUSIC x$
107+ BGMを演奏する。詳細は、下記<MUSIC>の項を参照。
108+PLAYWAVE x$[,y]
109+ 音楽用のWAVEファイル(ファイル名をx$で指定)を演奏する。WAVEのフォーマットは、
110+ モノラル、ビット長は8、サンプリング周波数が15700 Hzの物を指定する。16000 Hz
111+ でも再生出来るが、音程と再生速度が少しずれる。yを指定した場合、指定の箇所から
112+ 再生される(1秒目から再生したい場合は、15700を指定)。x$に長さ0の文字列を指
113+ 定すると、現在再生中の音楽が停止する。
114+VAR xxx [, yyy [, zzz [, ... ]]]
115+ サブルーチン内で使う、ローカル変数を指定する。xxx, yyy等は、A-Zの
116+ アルファベットで指定する。
117+USEVAR xxx [, yyy [, zzz [, ... ]]]
118+ 英数字で最大6文字までの変数名を使用できるようにする。
119+ このステートメント以降でxxx, yyy等の長い変数名が使用可能となる。
120+WHILE x
121+WEND
122+ x が0以外の場合、WHILE文からWEND文までのステートメントを繰り返し実行する。
123+PALETTE n,r,g,b
124+ パレット指定。
125+PCG x,y,z
126+ ASCIIコードがxの文字の表示キャラクターを変更する。y,zは、キャラク
127+ ターデーター。詳細は、下記<PCG>の項を参照。
128+POKE x,y
129+ xで示される物理的アドレスに、yで示される値(1バイト値)を書き込む。
130+PRINT [ xまたはx$またはx# [ ,または; [ yまたはy$またはy# [ ... ]]]]
131+ ディスプレイに、整数値または文字列を表示する。「;」を使用した場
132+ 合、次の表示が続けて行われる。「,」を使用した場合、10文字ずつ
133+ に区切って表示される。どちらも使用しない場合、次の表示は行を変え
134+ て行われる。
135+REM xxx
136+ 何も実行しない
137+RESTORE xxx
138+ DATA読み出し開始位置を指定。xxxは行番号もしくはラベル。
139+RETURN
140+ 最後に実行されたGOSUB文の次のステートメントに移動する。戻り値を指
141+ 定することがができる。この場合の戻り値はGOSUB()関数にて取得が可能。
142+SCROLL x,y
143+ 画面を横方向、もしくは縦方向(斜めも可)に動かす。動かす方向と大きさ
144+ は、x, yでそれぞれ、横方向の移動度、縦方向の移動度として指定する。
145+SOUND xxx
146+ 効果音を再生する。詳細は、下記<SOUND>の項を参照。xxxは行番号もしく
147+ はラベル。
148+SYSTEM x , y
149+ 様々なシステム値の設定を行なう。<SYSTEM>の項を参照。
150+USEGRAPHIC [x]
151+ グラフィックディスプレイを使用、もしくは使用停止する。x=0で使用停止、
152+ x=1で使用、x=2で画面とパレットをクリアーして使用、x=3でグラフィック領
153+ 域を確保するが表示はキャラクターディスプレイのまま。ただし、グラフィッ
154+ クディスプレイ未使用の状態でx=0の場合は、領域を確保する。xを省略した場
155+ 合は、x=1と同じ。
156+USEPCG [x]
157+ PCGを使用、もしくは使用停止する。x=0で使用停止、x=1で使用、x=2で
158+ キャラクターをリセットして使用。xを省略した場合は、x=1と同じ。
159+WAIT x
160+ xで示された時間、プログラムの実行を停止する。xが60の場合、約1秒間
161+ 停止。
162+WIDTH x
163+ キャラクターディスプレイの横幅を文字数で指定。xは30もしくは40。
164+
165+<グラフィック関連命令>
166+
167+BOXFILL [x1,y1],x2,y2[,c]
168+ 座標(x1,y1),(x2,y2)を対角線とするカラーcで塗られた長方形を描画。
169+CIRCLE [x,y],r[,c]
170+ 座標(x,y)を中心に、半径r、カラーcの円を描画。
171+CIRCLEFILL [x,y],r[,c]
172+ 座標(x,y)を中心に、半径r、カラーcで塗られた円を描画。
173+GCLS
174+ 画面クリアー。
175+GCOLOR c
176+ それぞれの命令で、cを省略した場合の色を指定。
177+GPALETTE n,r,g,b
178+ パレット指定。
179+GPRINT [x,y],c,bc,s$
180+ 座標(x,y)にカラーcで文字列s$を表示、bc:背景色(負数の場合背景色指定なし)。
181+LINE [x1,y1],x2,y2[,c]
182+ 座標(x1,y1)から(x2,y2)にカラーcで線分を描画。
183+POINT x,y
184+ グラフィック現在位置を、設定する。
185+PSET [x,y][,c]
186+ 座標(x,y)の位置にカラーcで点を描画。
187+PUTBMP [x,y],m,n,bbb
188+ 横m*縦nドットのキャラクター(bbbで指定)を座標(x,y)に表示。
189+ サイズm*nの配列bmpに、単純にカラー番号を並べる。
190+ ただし、カラーが0の部分は透明色として扱う。ただし、bbbはラベル名もし
191+ くは配列へのポインター。
192+(GCOLOR()関数も参照のこと)
193+
194+<ファイル関連命令>
195+FCLOSE [x]
196+ ファイルを閉じる。引数(x)がある場合は、そのファイルハンドルで指定されたファ
197+ イルを閉じる。
198+FGET x,y
199+ バッファー(xに配列として指定)にyバイト読み込む。関数として呼ばれた場合は、
200+ 読み込みに成功したバイト数を返す。
201+FILE x
202+ アクティブなファイルハンドル(1もしくは2)をxに指定する。
203+FOPEN x$,y$[,z]
204+ x$で示される名前のファイルを、y$で示されたモードで開く。同時に開けるファイ
205+ ルの数は、2つまで。関数として呼ばれた場合は、ファイルハンドルを返す。y$と
206+ しては、次のものが有効。
207+ "r" :ファイルを読み込みモードで開く。
208+ "r+" :"r"と同じだが書き込みも可能。
209+ "w" :ファイルを書き込みモードで開く。同名のファイルが在る場合は、
210+ 以前のファイルは消去される。
211+ "w+" :"w"と同じだが、読み込みも可能。
212+ "a" :ファイルを書き込みモードで開く。同名のファイルが在る場合は、
213+ ファイルは消去されず、ファイルの最後尾から書き込まれる。
214+ "a+" :"a"と同じだが、読み込みも可能。
215+ zには、割り当てたいファイルハンドル(1もしくは2)を指定する。省略した場
216+ 合、1が指定される。
217+FPRINT [ xまたはx$またはx# [ ,または; [ yまたはy$またはy# [ ... ]]]]
218+ PRINT命令と同じだが、画面ではなくファイルに情報が書き込まれる。
219+FPUT x,y
220+ バッファー(xに配列として指定)のyバイト分を書き込む。関数として呼ばれた場合
221+ は、書き込みに成功したバイト数を返す。
222+FPUTC x
223+ xで示される1バイトのデーターをファイルに書き込む。関数として呼ばれた場合
224+ は、書き込みに成功したバイト数(1もしくは0)を返す。
225+FREMOVE x$
226+ x$で示される名前のファイルを、SDカードから削除する。関数として呼ばれた場合
227+ は、削除に成功したか(0)、失敗したか(-1)を返す。
228+FSEEK x
229+ xで示されるファイル位置に移動する。
230+(FEOF(), FGETC(), FINPUT$(), FLEN(), FSEEK()関数も参照のこと)
231+
232+
233+<整数型関数>
234+以下、x, y, zは整数値を、x$, y$, z$は文字列を指します。[ ]は省略可能である事
235+を示します。
236+
237+ABS(x)
238+ xの絶対値を返す。
239+ARGS(x)
240+ サブルーチン中で、GOSUBに渡されたx番目の引数を整数値として取り出す。
241+ASC(x$)
242+ 文字列の最初の一文字の、アスキーコードを返す。
243+CREAD()
244+ DATA文の後から、一つずつデーター(8ビット整数値)を読み出す。「READ()」
245+ 関数も参照。
246+DRAWCOUNT()
247+ DRAWCOUNT値を得る。DRAWCOUNTは16ビット整数値で、1/60秒ごとに1ずつ
248+ 増える。
249+FEOF()
250+ FOPENで開いたファイルの現在のファイル位置が、末端に到達しているかどうか
251+ を返す。1で末端に到達、0で未到達。
252+FGETC()
253+ FOPENで開いたファイルから1バイト読み込み、整数値として返す。ファイル
254+ 末端に到達しているなどで読み込みに失敗した場合、-1を返す。
255+FLEN()
256+ FOPENで開いたファイルのファイル長を、バイト数で返す。
257+FSEEK()
258+ FOPENで開いたファイルの、現在のファイル位置を返す。
259+GCOLOR(x,y)
260+ グラフィック座標(x,y)の表示中パレット番号を返す。
261+GOSUB(xxx [, y [, z [, ... ]]])
262+ GOSUB命令と同じだが、戻り値(RETURNを参照)を得ることが出来る。xxxは、
263+ ラベルもしくは行番号。。yyy, zzz 等は、サブルーチンに引き継がれる引数(
264+ ARGS()関数を参照)。
265+INKEY([x])
266+ xを指定しない場合、現在押されているキーのASCII値を返す。押されていな
267+ い場合は、0。ASCII値でxを指定した場合、そのキーが押されているかどう
268+ かを返す。
269+INT(x#)
270+ 実数値x#を整数値に変換して返す。
271+KEYS([x])
272+ キー入力を得る。xの値は以下の通り。xを指定しない場合は、x=63と同じ。
273+ KEYUP: 1
274+ KEYDOWN: 2
275+ KEYLEFT: 4
276+ KEYRIGHT: 8
277+ KEYSTART: 16
278+ KEYFIRE: 32
279+LEN(x$)
280+ 文字列の長さを返す。
281+MUSIC()
282+ BGMの演奏の残り数を返す。
283+NOT(x)
284+ x=0の場合に1を、そうでない場合に0を返す。
285+PEEK(x)
286+ xで示される物理アドレスから1バイト読み取り、返す。
287+PLAYWAVE([x])
288+ xを指定しない場合、もしくは0を指定した場合、再生中のWAVEファイルの残りサン
289+ プリング数を返す。1を指定した場合、現在再生中のサンプリング番号を、2を指
290+ 定した場合、WAVEファイルの総サンプリング数を返す。
291+READ()
292+ DATA文の後から、一つずつデーター(32ビット整数値)を読み出す。「CREAD()」
293+ 関数も参照。
294+RND()
295+ 0から32767までの擬似乱数を返す。
296+SGN(x)
297+ xの符号(-1, 0, または1)を返す。
298+STRNCMP(x$,y$,z)
299+ 2つの文字列のうちz文字分を比較し、結果を返す。同じ文字列の場合は0。
300+SYSTEM(x)
301+ 様々なシステム値を、整数値で返す。「<システム変数>」の項を参照。
302+TVRAM([x])
303+ ビデオRAMのx番目の内容を、バイト値で返す。xを省略した場合、ビデオ
304+ RAMの開始位置の物理アドレスを返す。
305+VAL(x$)
306+ 10進数もしくは16進数文字列としてのx$の値を、整数値で返す。
307+
308+<浮動小数点型関数>
309+ACOS#(x#)
310+ x# の逆余弦を実数値で返す。
311+ARGS#(x)
312+ サブルーチン中で、GOSUBに渡されたx番目の引数を実数値として取り出す。
313+ASIN#(x#)
314+ x# の逆正弦を実数値で返す。
315+ATAN#(x#)
316+ x# の逆正接を実数値で返す。
317+ATAN2#(y#,x#)
318+ y#/x# の逆正接を実数値で返す。
319+CEIL#(x#)
320+ x# 以上の最小の整数を実数値で返す。
321+COS#(x#)
322+ x# の余弦を実数値で返す。
323+COSH#(x#)
324+ x# の双曲線余弦を実数値で返す。
325+EXP#(x#)
326+ eを底とする x# の指数関数値を実数値で返す。
327+FABS#(x#)
328+ x# の絶対値を実数値で返す。
329+FLOAT#(x)
330+ 整数値 x を浮動小数点型実数値に変換して返す。
331+FLOOR#(x#)
332+ x# 以下の最大の整数を実数値で返す。
333+FMOD#(x#,y#)
334+ x# を y# で割った剰余を実数値で返す。
335+GOSUB#(xxx [, y [, z [, ... ]]])
336+ GOSUB命令と同じだが、戻り値(RETURNを参照)を得ることが出来る。xxxは、
337+ ラベルもしくは行番号。。yyy, zzz 等は、サブルーチンに引き継がれる引数(
338+ ARGS()関数を参照)。
339+LOG#(x#)
340+ x# の自然対数を実数値で返す。
341+LOG10#(x#)
342+ x# の常用対数を実数値で返す。
343+MODF#(x#)
344+ x# の小数部を実数値で返す。
345+PI#
346+ 3.141593を返す。
347+POW#(x#,y#)
348+ x# の y# 乗を実数値で返す。
349+SIN#(x#)
350+ x# の正弦を実数値で返す。
351+SINH#(x#)
352+ x# の双曲線正弦を実数値で返す。
353+SQRT#(x#)
354+ x# の平方根を実数値で返す。
355+TAN#(x#)
356+ x# の正接を実数値で返す。
357+TANH#(x#)
358+ x# の双曲線正接を実数値で返す。
359+VAL#(x$)
360+ 10進数文字列としてのx$の値を、実数値で返す。
361+
362+<文字列型関数>
363+A$(x [,y])など
364+ xの値が0の場合、文字列全体を返す。
365+ xの値が正の場合、xで示される位置より右側の文字列を返す。
366+ xの値が負のとき、文字列の右側x文字を返す。
367+ yが指定された場合、y文字分の文字列を返す。
368+ARGS$(x)
369+ サブルーチン中で、GOSUBに渡されたx番目の引数を文字列として取り出す。
370+CHR$(x)
371+ xをアスキーコードとする文字を返す。
372+DEC$(x)
373+ xの値を、10進数の文字列として返す。
374+FINPUT$([x])
375+ FOPENで開いたファイルから、xで示された長さの文字列を読み込む。xが省略された
376+ 場合は、行の最後まで読み込む(改行コードが含まれる)。
377+FLOAT$(x#)
378+ 実数値x#を、10進数の文字列として返す。
379+GOSUB$(xxx [, y [, z [, ... ]]])
380+ GOSUB命令と同じだが、戻り値(RETURNを参照)を文字列として得ることが出来る。
381+ xxxは、ラベルもしくは行番号。。yyy, zzz 等は、サブルーチンに引き継がれる引数
382+ (ARGS()関数を参照)。
383+HEX$(x [,y])
384+ xの値を、16進数の文字列として返す。yが指定された場合、yバイト長の
385+ 文字列になる。
386+INPUT$()
387+ 文字列入力状態になり、入力が終了すると(Enterが押されると)文字列を返す。
388+SPRINTF$(x$,y#)
389+ x$で示される書式に従って、実数y#の内容を文字列として返す。
390+SYSTEM$(x)
391+ 様々なシステム値を、文字列で返す。「<システム変数>」の項を参照。
392+READ$()
393+ DATA文の後から、一つずつ文字列データーを読み出す。
394+
395+<整数演算子>
396+-x
397+ 符号を反転
398+x + y
399+ 整数加算
400+x - y
401+ 整数減算
402+x * y
403+ 整数乗算
404+x / y
405+ 整数除算
406+x % y
407+ 整数剰余
408+x >> y
409+ xの値をyビット右シフト
410+x << y
411+ xの値をyビット左シフト
412+x = y
413+ 2つの整数値が等しい場合に1、そうでないときに0
414+x != y
415+ 2つの整数値が等しい場合に0、そうでないときに1
416+x < y
417+ xがyより小さい場合に1、そうでないときに0
418+x <= y
419+ xがyより小さいか等しい場合に1、そうでないときに0
420+x > y
421+ xがyより多きい場合に1、そうでないときに0
422+x >= y
423+ xがyより多きいか等しい場合に1、そうでないときに0
424+x AND y
425+ xとyの値のビットごとの AND(論理積でないことに注意)
426+x OR y
427+ xとyの値のビットごとの OR
428+x XOR y
429+ xとyの値のビットごとの XOR
430+
431+なお、整数演算子の優先順位は、優先度が高いものから以下の順です。
432+
433++ - (単項演算子)
434+* / %
435++ - (加算・減算)
436+<< >>
437+< <= > >=
438+= !=
439+XOR
440+AND
441+OR
442+
443+<文字列演算子>
444+x$ + y$
445+ 文字列の連結
446+
447+<浮動小数点型演算子>
448+-x#
449+ 符号を反転
450+x# + y#
451+ 実数加算
452+x# - y#
453+ 実数減算
454+x# * y#
455+ 実数乗算
456+x# / y#
457+ 実数除算
458+x# = y#
459+ 2つの実数値が等しい場合に1、そうでないときに0
460+x# != y#
461+ 2つの実数値が等しい場合に0、そうでないときに1
462+x# < y#
463+ xがyより小さい場合に1、そうでないときに0
464+x# <= y#
465+ xがyより小さいか等しい場合に1、そうでないときに0
466+x# > y#
467+ xがyより多きい場合に1、そうでないときに0
468+x# >= y#
469+ xがyより多きいか等しい場合に1、そうでないときに0
470+x# AND y#
471+ xとyの値の論理積(ビットごとの AND でないことに注意)
472+x# OR y#
473+ xとyの値の論理和(ビットごとの OR でないことに注意)
474+
475+なお、実数演算子の優先順位は、優先度が高いものから以下の順です。
476+
477++ - (単項演算子)
478+* /
479++ - (加算・減算)
480+< <= > >=
481+= !=
482+AND
483+OR
484+
485+<MUSIC>
486+MUSIC命令では、BGM用のデーターを文字列で指定します。文字列の書式は、ABC
487+notationに準拠しています。ただし、すべての記法が使えるわけではありません。
488+なお、キーや速度などのデフォルト設定値は以下の通りです。
489+
490+Q: 1/4=90
491+L: 1/8
492+K: C
493+
494+BGM演奏時に一度に設定できる音の数は、31迄です。これを超えて音楽を再生したい
495+場合は、MUSIC()関数の戻り値を調べ、その値が十分小さくなってから、次のMUSIC命
496+令を実行するようにします。
497+
498+添付のmusic.basに、使い方に関するサンプルがありますので、参考にして下さい。
499+
500+<SOUND>
501+SOUND命令では、DATA列のデーターを、行番号もしくはラベルで指定します。SOUND命
502+令による効果音再生中は、BGMは再生されません。また、前の効果音が終わる前に次
503+のSOUND命令を実行すると、前の効果音の再生は停止し、新しい効果音がすぐに再生
504+されます。
505+
506+DATA列では、32ビット整数値として、交換音を表現します。この整数値の下位16
507+ビットは周波数の指定です。2048が440Hz(ラの音)に対応します。値が大きくなるほ
508+ど、より低い音が出ます。上位16ビットは、音の長さです。1が、1/60秒に相当し
509+ます。最後に、65535以下の値で、効果音の繰り返し回数を指定します。これらのデー
510+ターの数は、32を超えないようにして下さい。
511+
512+添付のsound.basに、使い方に関するサンプルがありますので、参考にして下さい。
513+
514+<PCG>
515+PCG(Programmable Character Generator)を用いると、ASCIIコードごとにフォント
516+を指定して、疑似グラフィックスとして表示させることが出来ます。使用する場合
517+は、まず
518+
519+USEPCG
520+
521+とします。フォントの変更は、PCGステートメントを用いて、
522+
523+PCG 0x80,0x80402010,0x08040201
524+
525+の様に設定します。この例では、ASCIIコード0x80の文字のフォントを設定してい
526+て、バックスラッシュの様な記号(左上から右下に向かう斜め線)が表示されるよう
527+になります。PCGの利用を停止し、オリジナルのフォントに戻す場合は、
528+
529+USEPCG 0
530+
531+とします。再度PCGを使用したい場合は、
532+
533+USEPCG
534+
535+として下さい。先に設定したフォントデーターが、復活します。なお、先に設定し
536+たフォントデーターを破棄してPCGの使用を始めたい場合は、
537+
538+USEPCG 2
539+
540+として下さい。
541+
542+<システム変数>
543+SYSTEM関数及びSYSTEMステートメントを用いて、各種システム情報をやりとりするこ
544+とが出来ます。
545+
546+SYSTEM$(0)
547+ MachiKania バージョン文字列、"Zoea"を返す。
548+SYSTEM$(1)
549+ MachiKania バージョン文字列、"1.0"等を返す。
550+SYSTEM$(2)
551+ BASIC バージョン文字列、"KM-1200"等を返す。
552+SYSTEM$(3)
553+ 現在実行中のHEXファイル名、"ZOEA.HEX"等を返す。
554+SYSTEM(20)
555+ キャラクターディスプレイ横幅を返す。
556+SYSTEM(21)
557+ キャラクターディスプレイ縦幅を返す。
558+SYSTEM(22)
559+ グラフィックディスプレイ横幅を返す。
560+SYSTEM(23)
561+ グラフィックディスプレイ横幅を返す。
562+SYSTEM(24)
563+ キャラクターディスプレイ用の指定色を返す。
564+SYSTEM(25)
565+ グラフィックディスプレイ用の指定色を返す。
566+SYSTEM(26)
567+ キャラクターディスプレイの、現在のX位置を返す。
568+SYSTEM(27)
569+ キャラクターディスプレイの、現在のY位置を返す。
570+SYSTEM(28)
571+ グラフィックディスプレイの、現在のX位置を返す。
572+SYSTEM(29)
573+ グラフィックディスプレイの、現在のY位置を返す。
574+SYSTEM(40)
575+ PS/2キーボードを使用中かどうかを返す。
576+SYSTEM(41)
577+ PS/2キーボード情報、vkeyを返す。
578+SYSTEM(42)
579+ PS/2キーボード情報、lockkeyを返す。
580+SYSTEM(43)
581+ PS/2キーボード情報、keytypeを返す。
582+SYSTEM(100)
583+ 変数格納領域(g_var_mem)へのポインターを返す。
584+SYSTEM(101)
585+ 乱数シードへのポインターを返す。
586+SYSTEM(102)
587+ キャラクターディスプレイ領域(TVRAM)へのポインターを返す。
588+SYSTEM(103)
589+ フォント領域へのポインターを返す。
590+SYSTEM(104)
591+ PCGフォント領域へのポインターを返す。
592+SYSTEM(105)
593+ グラフィックディスプレイ領域へのポインターを返す。
594+SYSTEM 200,x
595+ ディスプレイの表示を停止(xが0のとき)、もしくは開始(xが0以外の時)する。
596+
597+<ヒント>
598+FOR-NEXTループ、WHILE-WENDループ、DO-LOOPループの途中で、GOTO文でループの
599+外に飛んだり、RETURN文を実行したりすると、予期せぬ結果(機器のリセット等)を
600+引き起こします。ただし、GOSUB文でサブルーチンを呼んだり、別のループをネスト
601+して使う事は可能です。
602+
603+ON GOTO分やON GOSUB文はサポートしていません。ただし、例えば次のように記述す
604+ることで、同様の動作をさせることは可能です。
605+ GOSUB 10000+A
606+ ....
607+ 10000 PRINT "A=0" : RETURN
608+ 10001 PRINT "A=1" : RETURN
609+ 10002 PRINT "A=2" : RETURN
610+
611+一行中で連続して文字列を扱うと、"String too complexed"というエラーがでて、
612+停止することがあります。この場合は、文字列を扱う命令を独立した行するか、文
613+字列関連の演算を幾つかのステップに分けて、それぞれ1行ずつの記述にして試し
614+てみて下さい。
615+
616+<バージョン履歴>
617+・KM-1206 2018年8月公開。
618+ 1.WAVEファイルの再生に対応。
619+・KM-1205 2018年2月公開。
620+ 1.スタック容量拡大のため、使用可能RAM容量を53Kバイトに削減。
621+ 2.CLEARステートメントの不具合を修正。
622+・KM-1204 2017年8月公開。
623+ 1.USEVARステートメントを追加。
624+ 2.CLEARステートメント実行でグラフィックモードから抜けるように変更。
625+・KM-1203 2017年1月公開。
626+ 1.ファイル入出力機能を追加。
627+・KM-1202 2016年10月公開。
628+ 1.WIDTHステートメントを追加。
629+ 2.特殊なデーター列・文字列に於ける、リンク時の不具合及びREAD()関数実行時
630+   に於ける不具合を修正。
631+ 3.多次元配列中で演算子を使った場合の不具合を解消。
632+・KM-1201 2016年9月公開。
633+ 1.CONTINUEステートメントを追加。
634+ 2.ATAN2#()関数を追加。
635+ 3.IF-THEN-ELSEステートメントでエラーがでる不具合を修正。
636+ 4.負の実数値の扱いにおける不具合を修正。
637+・KM-1200 2016年8月公開。
638+ 1.グラフィックディスプレイ機能および、関連のステートメント群を追加。
639+ 2.浮動小数点演算機能、及び、算術演算関数群を追加。
640+ 3.VAR, BREAK, SYSTEMステートメントを追加。
641+ 4.DO-LOOP, WHILE-WENDループ構造文を追加。
642+ 5.IF THEN - ELSEIF - ELSE - ENDIFによる、複数行での条件分岐表現を追加。
643+ 6.GOSUBステートメント及びGOSUB()関数に第二以降の引数を指定出来る様にし、
644+   サブルーチン中でARGS()関数により取り出せるようにした。
645+ 7.8ビット整数型を扱うCDATAステートメントとCREAD()関数を追加。
646+ 8.DATAステートメントで文字列を扱える様にし、READ$()で読めるようにした。
647+ 9.多次元配列をサポート。
648+ 10.例外発生時に、情報を表示するようにした。
649+ 11.FOR-NEXTループに於いて、TO値に一致する時だけではなく、値を超えた場合
650+   でもループを抜けるようにした。
651+ 12.MUSICステートメント用のスクリプトにエラーがある際、エラー発生行が正し
652+   く表示されない不具合を修正。
653+ 13.ビットシフト演算子を、追加。
654+
655+・KM-1120 2016年2月公開。
656+ 1.PCG機能を追加。
657+ 2.SCROLL命令を追加。
658+ 3.WAIT命令を追加。
659+ 4.「Ctrl+Break」キーによる実行停止に対応。
660+ 5.FOR無しでNEXTを実行した場合、GOSUB無しでRETURNを実行した場合にエラー
661+   を表示して停止するようにした。
662+
663+・Ver 1.1.0 (KM-1110) 2015年12月公開。
664+ 1.2015年11月21日に変更されたPIC32TVGSの仕様に対応。
665+ 2.PS/2キーボードに対応。
666+ 3.INKEY() INPUT$() VAL() DEC$() の4つの関数を追加。
667+ 4.TVRAM() ASC() PEEK()が、0x80-0xFFの値に関して負の数を返していた不具合
668+   を修正。
669+ 5.DIMステートメントにより配列を定義した際、すべての要素がゼロになるよう
670+   にした。
671+ 6.単項演算子、「-」「+」を追加。
672+ 7.LABEL定義されていない飛び先にGOTOするとリセットされる不具合を修正。
673+ 8.同一のLABELを複数回使用している場合に、コンパイルエラーが出るように修
674+   正。
675+ 9.引数を持たないPRINT文に対応。
676+
677+・Ver 1.0.5 (KM-1100) 最初の正規公開バージョン。
--- mips/branches/zoeaobjective/music.c (nonexistent)
+++ mips/branches/zoeaobjective/music.c (revision 271)
@@ -0,0 +1,639 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by Katsumi.
4+ http://hp.vector.co.jp/authors/VA016157/
5+ kmorimatsu@users.sourceforge.jp
6+*/
7+
8+#include <xc.h>
9+#include "compiler.h"
10+#include "api.h"
11+
12+/*
13+ Timer3: 1/32 prescaler, toggle mode : 894886.25 Hz
14+ PR3=2047 <-> 437 Hz
15+*/
16+
17+/*
18+ c: 1722
19+ B: 1825
20+ A#: 1933
21+ A: 2048
22+ G#: 2170
23+ G: 2299
24+ F#: 2435
25+ F: 2580
26+ E: 2734
27+ D#: 2896
28+ D: 3067
29+ C#: 3251
30+ C: 3444
31+ Cb: 3650
32+*/
33+
34+const static int g_keys[]={
35+ 1933,1722,3251,2896,2580,2435,2170,// 0 7# C# A#m
36+ 1933,1825,3251,2896,2580,2435,2170,// 7 6# F# D#m
37+ 1933,1825,3251,2896,2734,2435,2170,// 14 5# B G#m
38+ 2048,1825,3251,2896,2734,2435,2170,// 21 4# E C#m
39+ 2048,1825,3251,3067,2734,2435,2170,// 28 3# A F#m
40+ 2048,1825,3251,3067,2734,2435,2299,// 35 2# D Bm
41+ 2048,1825,3444,3067,2734,2435,2299,// 42 1# G Em
42+ 2048,1825,3444,3067,2734,2580,2299,// 49 0 C Am
43+ 2048,1933,3444,3067,2734,2580,2299,// 56 1b F Dm
44+ 2048,1933,3444,3067,2896,2580,2299,// 63 2b Bb Gm
45+ 2170,1933,3444,3067,2896,2580,2299,// 70 3b Eb Cm
46+ 2170,1933,3444,3251,2896,2580,2299,// 77 4b Ab Fm
47+ 2170,1933,3444,3251,2896,2580,2435,// 84 5b Db Bbm
48+ 2170,1933,3650,3251,2896,2580,2435,// 91 6b Gb Ebm
49+ 2170,1933,3650,3251,2896,2734,2435 // 98 7b Cb Abm
50+};
51+
52+/*
53+ 2^(1/12) ~= 69433/(2^16)
54+ 1/(2^(1/12) ~= 1933/(2^11)
55+*/
56+
57+#define toneFlat(x) ((((unsigned long)(x))*69433)>>16)
58+#define toneSharp(x) ((((unsigned long)(x))*1933)>>11)
59+
60+/* local global vars */
61+static int* g_tones;
62+static int g_qvalue;
63+static int g_lvalue;
64+static int g_mpoint;
65+static char* g_mstr;
66+static int g_mspos;
67+static unsigned short g_music[32];
68+static unsigned short g_sound[32];
69+static unsigned short g_musiclen[32];
70+static unsigned char g_soundlen[32];
71+static int g_musicstart;
72+static int g_musicend;
73+static int g_musicwait;
74+static int g_soundstart;
75+static int g_soundend;
76+static int g_soundwait;
77+static int g_soundrepeat;
78+
79+static char g_sound_mode=0;
80+static FSFILE* g_fhandle=0;
81+static char* g_wavtable=0;
82+
83+#define SOUND_MODE_MUSIC 1
84+#define SOUND_MODE_WAVE 2
85+
86+#define start_dma() T4CONSET=0x8000; DCH2CONSET=0x00000080; g_sound_mode=SOUND_MODE_WAVE
87+#define stop_dma() T4CONCLR=0x8000; DCH2CONCLR=0x00000080; g_sound_mode=SOUND_MODE_MUSIC
88+
89+int waveRemaining(int mode){
90+ if (!g_fhandle) return 0;
91+ switch(mode){
92+ case 1: // current position (header excluded)
93+ return g_fhandle->seek-0x2c;
94+ break;
95+ case 2: // file size (header excluded)
96+ return g_fhandle->size-0x2c;
97+ break;
98+ case 0: // remaining
99+ default:
100+ return g_fhandle->size-g_fhandle->seek;
101+ break;
102+ }
103+}
104+int musicRemaining(int flagsLR){
105+ // flagsLR is ignored
106+ return (g_musicend-g_musicstart)&31;
107+}
108+
109+#pragma interrupt musicint IPL3SOFT vector 1
110+void musicint(){
111+ unsigned int i;
112+ static unsigned short wavtable_pos;
113+ // This function is called every 1/60 sec.
114+ IFS0bits.CS0IF=0;
115+ switch(g_sound_mode){
116+ case SOUND_MODE_MUSIC:
117+ if (g_soundstart!=g_soundend){
118+ // Start timer & OC4
119+ i=g_sound[g_soundstart];
120+ if (i<0xffff) {
121+ T3CONSET=0x8000;
122+ PR3=i;
123+ if (i<TMR3) TMR3=0;
124+ } else {
125+ T3CONCLR=0x8000;
126+ }
127+ if ((--g_soundwait)<=0) {
128+ g_soundstart++;
129+ if (g_soundstart==g_soundend || 31<g_soundstart) {
130+ g_soundstart=0;
131+ g_soundrepeat--;
132+ if (0<g_soundrepeat) {
133+ g_soundwait=g_soundlen[g_soundstart];
134+ } else {
135+ g_soundend=g_soundrepeat=g_soundwait=0;
136+ }
137+ } else {
138+ g_soundwait=g_soundlen[g_soundstart];
139+ }
140+ }
141+ // Shift music data even though without output.
142+ if (g_musicstart!=g_musicend) {
143+ if ((--g_musicwait)<=0) {
144+ g_musicstart++;
145+ g_musicstart&=31;
146+ g_musicwait=g_musiclen[g_musicstart];
147+ }
148+ }
149+ } else if (g_musicstart!=g_musicend) {
150+ // Start timer & OC4
151+ i=g_music[g_musicstart];
152+ if (i<0xffff) {
153+ T3CONSET=0x8000;
154+ PR3=i;
155+ if (i<TMR3) TMR3=0;
156+ } else {
157+ T3CONCLR=0x8000;
158+ }
159+ if ((--g_musicwait)<=0) {
160+ g_musicstart++;
161+ g_musicstart&=31;
162+ g_musicwait=g_musiclen[g_musicstart];
163+ }
164+ } else {
165+ // Stop timer
166+ T3CONCLR=0x8000;
167+ }
168+ break;
169+ case SOUND_MODE_WAVE:
170+ // Initialize parameters
171+ if (!T4CONbits.ON){
172+ start_dma();
173+ wavtable_pos=0;
174+ }
175+ wavtable_pos=262-wavtable_pos;
176+ // Read from file
177+ if (0 == FSfread((void*)&g_wavtable[wavtable_pos],1,262,g_fhandle)) {
178+ // End of file.
179+ stop_dma();
180+ FSfclose(g_fhandle);
181+ g_fhandle=0;
182+ g_sound_mode=SOUND_MODE_MUSIC;
183+ stop_music();
184+ break;
185+ }
186+ break;
187+ default:
188+ break;
189+ }
190+}
191+
192+int musicGetNum(){
193+ int i, ret;
194+ char b;
195+ // Skip non number character
196+ for(i=0;(b=g_mstr[g_mspos+i])<'0' && '9'<g_mstr[g_mspos+i];i++);
197+ // Determine the number
198+ ret=0;
199+ while('0'<=b && b<='9'){
200+ ret*=10;
201+ ret+=b-'0';
202+ i++;
203+ b=g_mstr[g_mspos+i];
204+ }
205+ g_mspos+=i;
206+ return ret;
207+}
208+
209+void stop_music(){
210+ // Initialize normal music mode.
211+
212+ // Use Timer3 and OC4 for sound.
213+ RPB13R=5; //Use RPB13 for OC4
214+ OC4R=0;
215+ OC4CON=0x000b; // Timer3, toggle mode
216+ OC4CONSET=0x8000;// Start OC4
217+ T3CON=0x0050; // Prescaller: 1:32 (1.8 MHz), not yet started
218+
219+ // Software interrupt every 1/60 sec (triggered by Timer5)
220+ IPC0bits.CS0IP=3;
221+ IPC0bits.CS0IS=0;
222+ IFS0bits.CS0IF=0;
223+ IEC0bits.CS0IE=1;
224+
225+ // Initializations for music/sound.
226+ g_musicstart=g_musicend=g_musicwait=g_soundstart=g_soundend=g_soundwait=g_soundrepeat=0;
227+ g_sound_mode=SOUND_MODE_MUSIC;
228+
229+ // Initialize DMA (see also init_dma_music())
230+
231+ // Stop Timer4
232+ T4CON=0x0000; // Not start yet
233+
234+ // Enable DMA, stop DMA2
235+ DMACONSET=0x8000;
236+ DCH2CONCLR=0x0080;
237+
238+ // Close handle if open.
239+ if (g_fhandle) FSfclose(g_fhandle);
240+ g_fhandle=0;
241+}
242+
243+void init_music(){
244+ // Initilize music system
245+ stop_music();
246+
247+ // Initializations for music/sound.
248+ g_qvalue=160; // Q: 1/4=90
249+ g_lvalue=20; // L: 1/8
250+ g_tones=(int*)&(g_keys[49]); // C major
251+}
252+
253+void musicSetL(){
254+ // Set length of a character.
255+ // Syntax: L:n/m, where n and m are numbers.
256+ int n,m;
257+ n=musicGetNum();
258+ g_mspos++;
259+ m=musicGetNum();
260+ g_lvalue=g_qvalue*n/m;
261+}
262+
263+void musicSetQ(){
264+ int i;
265+ // Syntax: Q:1/4=n, where n is number.
266+ // Skip "1/4="
267+ for(i=0;g_mstr[g_mspos+i]!='=';i++);
268+ g_mspos+=i+1;
269+ i=musicGetNum();
270+ if (i<48) { g_qvalue=320; /* 1/4=45 */ }
271+ else if (i<53) { g_qvalue=288; /* 1/4=50 */ }
272+ else if (i<60) { g_qvalue=256; /* 1/4=56 */ }
273+ else if (i<70) { g_qvalue=224; /* 1/4=64 */ }
274+ else if (i<83) { g_qvalue=192; /* 1/4=75 */ }
275+ else if (i<102) { g_qvalue=160; /* 1/4=90 */ }
276+ else if (i<132) { g_qvalue=128; /* 1/4=113 */ }
277+ else if (i<188) { g_qvalue=96; /* 1/4=150 */ }
278+ else { g_qvalue=64; /* 1/4=225 */ }
279+ g_lvalue=g_qvalue>>3;
280+}
281+
282+void musicSetK(){
283+ // Syntax: K:xxx
284+ if (!strncmp((char*)&(g_mstr[g_mspos]),"A#m",3)) {
285+ g_mspos+=3;
286+ g_tones=(int*)&(g_keys[0]);
287+ return;
288+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"D#m",3)) {
289+ g_mspos+=3;
290+ g_tones=(int*)&(g_keys[7]);
291+ return;
292+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"G#m",3)) {
293+ g_mspos+=3;
294+ g_tones=(int*)&(g_keys[14]);
295+ return;
296+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"C#m",3)) {
297+ g_mspos+=3;
298+ g_tones=(int*)&(g_keys[21]);
299+ return;
300+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"F#m",3)) {
301+ g_mspos+=3;
302+ g_tones=(int*)&(g_keys[28]);
303+ return;
304+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Bbm",3)) {
305+ g_mspos+=3;
306+ g_tones=(int*)&(g_keys[84]);
307+ return;
308+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Ebm",3)) {
309+ g_mspos+=3;
310+ g_tones=(int*)&(g_keys[91]);
311+ return;
312+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Abm",3)) {
313+ g_mspos+=3;
314+ g_tones=(int*)&(g_keys[98]);
315+ return;
316+ }
317+ if (!strncmp((char*)&(g_mstr[g_mspos]),"C#",2)) {
318+ g_mspos+=2;
319+ g_tones=(int*)&(g_keys[0]);
320+ return;
321+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"F#",2)) {
322+ g_mspos+=2;
323+ g_tones=(int*)&(g_keys[7]);
324+ return;
325+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Bm",2)) {
326+ g_mspos+=2;
327+ g_tones=(int*)&(g_keys[35]);
328+ return;
329+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Em",2)) {
330+ g_mspos+=2;
331+ g_tones=(int*)&(g_keys[42]);
332+ return;
333+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Am",2)) {
334+ g_mspos+=2;
335+ g_tones=(int*)&(g_keys[49]);
336+ return;
337+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Dm",2)) {
338+ g_mspos+=2;
339+ g_tones=(int*)&(g_keys[56]);
340+ return;
341+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Gm",2) || !strncmp((char*)&(g_mstr[g_mspos]),"Bb",2)) {
342+ g_mspos+=2;
343+ g_tones=(int*)&(g_keys[63]);
344+ return;
345+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Cm",2) || !strncmp((char*)&(g_mstr[g_mspos]),"Eb",2)) {
346+ g_mspos+=2;
347+ g_tones=(int*)&(g_keys[70]);
348+ return;
349+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Fm",2) || !strncmp((char*)&(g_mstr[g_mspos]),"Ab",2)) {
350+ g_mspos+=2;
351+ g_tones=(int*)&(g_keys[77]);
352+ return;
353+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Db",2)) {
354+ g_mspos+=2;
355+ g_tones=(int*)&(g_keys[84]);
356+ return;
357+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Gb",2)) {
358+ g_mspos+=2;
359+ g_tones=(int*)&(g_keys[91]);
360+ return;
361+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Cb",2)) {
362+ g_mspos+=2;
363+ g_tones=(int*)&(g_keys[98]);
364+ return;
365+ }
366+ switch(g_mstr[g_mspos]){
367+ case 'B':
368+ g_mspos++;
369+ g_tones=(int*)&(g_keys[14]);
370+ return;
371+ case 'E':
372+ g_mspos++;
373+ g_tones=(int*)&(g_keys[21]);
374+ return;
375+ case 'A':
376+ g_mspos++;
377+ g_tones=(int*)&(g_keys[28]);
378+ return;
379+ case 'D':
380+ g_mspos++;
381+ g_tones=(int*)&(g_keys[35]);
382+ return;
383+ case 'G':
384+ g_mspos++;
385+ g_tones=(int*)&(g_keys[42]);
386+ return;
387+ case 'C':
388+ g_mspos++;
389+ g_tones=(int*)&(g_keys[49]);
390+ return;
391+ case 'F':
392+ g_mspos++;
393+ g_tones=(int*)&(g_keys[56]);
394+ return;
395+ default:
396+ err_music(g_mstr);
397+ break;
398+ }
399+}
400+void musicSetM(){
401+ // Currently do nothing
402+ musicGetNum();
403+ musicGetNum();
404+}
405+
406+void set_sound(unsigned long* data, int flagsLR){
407+ // flagsLR is ignored
408+ int sound;
409+ int len;
410+ int pos;
411+ int datalen;
412+ IEC0bits.T4IE=0; // Stop interruption, first.
413+ // Initialize
414+ g_soundrepeat=g_soundstart=g_soundend=0;
415+ pos=0;
416+ do {
417+ while(data[1]!=0x00000020) data++; // Seek DATA statement
418+ datalen=(data[0]&0x00007FFF)-1; // Use bgezal statement containing data length.
419+ data+=2;
420+ while(0<datalen){
421+ datalen--;
422+ len=data[0]>>16;
423+ sound=data[0]&0x0000FFFF;
424+ data++;
425+ if (len) {
426+ // Shift tone if graphic is used
427+ if (g_use_graphic) {
428+ // MUL_15 instead of MUL_16 for CPU clock.
429+ // sound=sound*15/16
430+ sound-=(sound+7)>>4;
431+ }
432+ g_sound[pos]=sound-1;
433+ g_soundlen[pos]=len;
434+ pos++;
435+ if (32<pos) {
436+ err_music("Sound data too long.");
437+ return;
438+ }
439+ } else {
440+ g_soundrepeat=sound;
441+ break;
442+ }
443+ }
444+ } while(len);
445+ g_soundend=pos;
446+ g_soundwait=g_soundlen[0];
447+ IEC0bits.T4IE=1; // Restart interrupt.
448+}
449+
450+void set_music(char* str, int flagsLR){
451+ // flagsLR is ignored
452+ char b;
453+ unsigned long tone,tonenatural;
454+ int len;
455+ g_mstr=str;
456+ g_mspos=0;
457+ while(0<(b=g_mstr[g_mspos])){
458+ if (g_mstr[g_mspos+1]==':') {
459+ // Set property
460+ g_mspos+=2;
461+ switch(b){
462+ case 'L':
463+ musicSetL();
464+ break;
465+ case 'Q':
466+ musicSetQ();
467+ break;
468+ case 'K':
469+ musicSetK();
470+ break;
471+ case 'M':
472+ musicSetM();
473+ break;
474+ default:
475+ err_music(str);
476+ break;
477+ }
478+ } else if ('A'<=b && b<='G' || 'a'<=b && b<='g' || b=='z') {
479+ g_mspos++;
480+ if (b=='z') {
481+ tone=0;
482+ } else if (b<='G') {
483+ tone=g_tones[b-'A'];
484+ tonenatural=g_keys[b-'A'+49];
485+ } else {
486+ tone=g_tones[b-'a']>>1;
487+ tonenatural=g_keys[b-'a'+49]>>1;
488+ }
489+ // Check "'"s
490+ while(g_mstr[g_mspos]=='\''){
491+ g_mspos++;
492+ tone>>=1;
493+ }
494+ // Check ","s
495+ while(g_mstr[g_mspos]==','){
496+ g_mspos++;
497+ tone<<=1;
498+ tonenatural<<=1;
499+ }
500+ // Check "^","=","_"
501+ switch(g_mstr[g_mspos]){
502+ case '^':
503+ g_mspos++;
504+ tone=toneSharp(tone);
505+ break;
506+ case '_':
507+ g_mspos++;
508+ tone=toneFlat(tone);
509+ break;
510+ case '=':
511+ g_mspos++;
512+ tone=tonenatural;
513+ break;
514+ default:
515+ break;
516+ }
517+ // Check number for length
518+ b=g_mstr[g_mspos];
519+ if ('0'<=b && b<='9') {
520+ len=g_lvalue*musicGetNum();
521+ } else {
522+ len=g_lvalue;
523+ }
524+ if (g_mstr[g_mspos]=='/') {
525+ g_mspos++;
526+ len=len/musicGetNum();
527+ }
528+ // Shift tone if graphic is used
529+ if (g_use_graphic) {
530+ // MUL_15 instead of MUL_16 for CPU clock.
531+ // tone=tone*15/16
532+ tone-=(tone+7)>>4;
533+ }
534+ // Update music value array
535+ IEC0bits.T4IE=0; // Stop interruption, first.
536+ if (g_musicstart==g_musicend) {
537+ g_musicwait=len;
538+ }
539+ g_music[g_musicend]=(tone-1)&0x0000FFFF;
540+ g_musiclen[g_musicend]=len;
541+ g_musicend++;
542+ g_musicend&=31;
543+ IEC0bits.T4IE=1; // Restart interruption.
544+ } else {
545+ err_music(str);
546+ }
547+ // Go to next character
548+ while(0<g_mstr[g_mspos] && g_mstr[g_mspos]<=0x20 || g_mstr[g_mspos]=='|') g_mspos++;
549+ }
550+}
551+
552+/*
553+ PLAYWAVE routines follow
554+*/
555+
556+int checkChars(char* str1, char* str2, int num){
557+ int i;
558+ for(i=0;i<num;i++){
559+ if (str1[i]!=str2[i]) return 1;
560+ }
561+ return 0;
562+}
563+
564+void init_dma_music(){
565+ // Timer4 for 15700 Hz
566+ T4CON=0x0000; // Not start yet
567+ if (g_use_graphic) {
568+ PR4=3405-1;
569+ } else {
570+ PR4=3632-1;
571+ }
572+ TMR4=PR4-1;
573+
574+ // Timer3 for PWM
575+ TMR3=0;
576+ PR3=0x100;
577+ T3CON=0x8000;
578+
579+ // OC4 setting
580+ RPB13R=5; //Use RPB13 for OC4
581+ OC4RS=0x80;
582+ OC4CON=0x000e;
583+ OC4CONSET=0x8000;
584+
585+ //DMA2 settings for OC4
586+ DMACONSET=0x8000;
587+ DCH2CON=0x00000012; // CHBUSY=0, CHCHNS=0, CHEN=0, CHAED=0, CHCHN=0, CHAEN=1, CHEDET=0, CHPRI=b10
588+ DCH2ECON=0x1310; // CHAIRQ=0, CHSIRQ=19, CFORCE=0, CABRT=0, PATEN=0, SIRQEN=1, AIRQEN=0
589+ // CHSIRQ=19: Timer4 interrupt
590+ DCH2SSA=((unsigned int)&(g_wavtable[0]))&0x1fffffff;
591+ DCH2DSA=0x1F803620; // OC4RS
592+ DCH2SSIZ=524;
593+ DCH2DSIZ=1;
594+ DCH2CSIZ=1;
595+ DCH2INTCLR=0x00FF00FF;
596+ DCH2CONSET=0x00000080;
597+}
598+
599+void play_wave(char* filename, int start){
600+ int i;
601+ // Stop the previous play
602+ stop_music();
603+ // Exit function if null filename
604+ if (filename[0]==0x00) {
605+ return;
606+ }
607+ // Alocate 524 byte buffer if not assigned
608+ if (g_var_size[ALLOC_WAVE_BLOCK]==0) {
609+ g_wavtable=(char*)alloc_memory(524/4,ALLOC_WAVE_BLOCK);
610+ }
611+ // Open file
612+ if (g_fhandle) FSfclose(g_fhandle);
613+ g_fhandle=FSfopen(filename,"r");
614+ if (!g_fhandle) err_file();
615+ // Read header and check if monaural 8 bit 16000 Hz.
616+ if (0x2c != FSfread((void*)&g_wavtable[0],1,0x2c,g_fhandle)) err_file();
617+ i=0;
618+ i+=checkChars((char*)&g_wavtable[0],"RIFF",4); // Check RIFF
619+ i+=checkChars((char*)&g_wavtable[8],"WAVEfmt ",8); // Check WAVE and fmt
620+ i+=checkChars((char*)&g_wavtable[16],"\x10\x00\x00\x00\x01\x00",6); // Check if liear PCM
621+ if (!checkChars((char*)&g_wavtable[22],"\x01\x00\x80\x3e\x00\x00\x80\x3e\x00\x00\x01\x00",12)) {
622+ // Monaural 16000 Hz
623+ } else if (!checkChars((char*)&g_wavtable[22],"\x01\x00\x54\x3d\x00\x00\x54\x3d\x00\x00\x01\x00",12)) {
624+ // Monaural 15700 Hz
625+ } else {
626+ i=1;
627+ }
628+ i+=checkChars((char*)&g_wavtable[34],"\x08\x00\x64\x61\x74\x61",6); // Check bit # and data
629+ if (i) err_wave();
630+ // Support defined start position here to skip file pointer here.
631+ FSfseek(g_fhandle, start, SEEK_CUR);
632+ // Read first 262 bytes.
633+ if (262 != FSfread((void*)&g_wavtable[0],1,262,g_fhandle)) err_file();
634+
635+ // Initialize DMA
636+ init_dma_music();
637+ g_sound_mode=SOUND_MODE_WAVE;
638+
639+}
--- mips/branches/zoeaobjective/editor.c (nonexistent)
+++ mips/branches/zoeaobjective/editor.c (revision 271)
@@ -0,0 +1,2554 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by K.Tanaka
4+ http://www.ze.em-net.ne.jp/~kenken/index.html
5+*/
6+
7+#include <xc.h>
8+#include "api.h"
9+#include "editor.h"
10+#include "keyinput.h"
11+#include "compiler.h"
12+#include "main.h"
13+
14+struct _TBUF{
15+//リンク付きのテキストバッファ
16+ struct _TBUF *prev;//前方へのリンク。NULLの場合先頭または空き
17+ struct _TBUF *next;//後方へのリンク。NULLの場合最後
18+ unsigned short n;//現在の使用バイト数
19+ unsigned char Buf[TBUFSIZE];//バッファ
20+} ;
21+typedef struct _TBUF _tbuf;
22+
23+//_tbuf TextBuffer[TBUFMAXLINE]; //テキストバッファ
24+_tbuf *TextBuffer; //実体は配列RAM[]の中に確保する
25+
26+_tbuf *TBufstart; //テキストバッファの先頭位置
27+_tbuf *cursorbp; //現在のカーソル位置のテキストバッファ
28+unsigned short cursorix; //現在のカーソル位置のテキストバッファ先頭からの位置
29+_tbuf *disptopbp; //現在表示中画面左上のテキストバッファ
30+unsigned short disptopix; //現在表示中画面左上のテキストバッファ先頭からの位置
31+int num; //現在バッファ内に格納されている文字数
32+int cx,cy; //カーソル座標
33+int cx2; //上下移動時の仮カーソルX座標
34+_tbuf *cursorbp1; //範囲選択時のカーソルスタート位置のテキストバッファ、範囲選択モードでない場合NULL
35+unsigned short cursorix1; //範囲選択時のカーソルスタート位置のテキストバッファ先頭からの位置
36+int cx1,cy1; //範囲選択時のカーソルスタート座標
37+int line_no; //現在のカーソル位置の行
38+int line_no1; //範囲選択時のカーソルスタート位置の行
39+
40+// カーソル関連位置の一時避難用
41+_tbuf *cursorbp_t;
42+unsigned short cursorix_t;
43+_tbuf *disptopbp_t;
44+unsigned short disptopix_t;
45+int cx_t,cy_t,line_no_t;
46+
47+//unsigned char clipboard[WIDTH_X2*EDITWIDTHY]; //クリップボード、最大サイズは編集画面領域と同じ
48+unsigned char *clipboard; //実体は配列RAM[]の中に確保する
49+
50+int clipsize; //現在クリップボードに格納されている文字数
51+int edited; //保存後に変更されたかを表すフラグ
52+
53+//配列RAM[]内にメモリ動的確保するためのポインタ
54+char *editormallocp;
55+
56+//unsigned char filebuf[FILEBUFSIZE]; //ファイルアクセス用バッファ
57+unsigned char *filebuf; //実体は配列RAM[]の中に確保する
58+
59+//unsigned char cwdpath[PATHNAMEMAX]; //現在のディレクトリのパス名
60+unsigned char *cwdpath; //実体は配列RAM[]の中に確保する
61+
62+unsigned char currentfile[13],tempfile[13]; //編集中のファイル名、一時ファイル名
63+
64+//unsigned char filenames[MAXFILENUM][13]; //ロード時のファイル名一覧バッファ
65+unsigned char (*filenames)[13]; //実体は配列RAM[]の中に確保する
66+
67+//unsigned char undobuf[UNDOBUFSIZE]; //アンドゥ用バッファ
68+unsigned char *undobuf; //実体は配列RAM[]の中に確保する
69+unsigned char *undobuf_top; //アンドゥ用バッファの先頭を指すポインタ
70+int undobuf_used; //アンドゥ用バッファ使用量
71+
72+const unsigned char Message1[]="Hit Any Key\n";
73+const unsigned char Message2[]="File System Error\n";
74+const unsigned char Message3[]="Retry:[Enter] / Quit:[ESC]\n";
75+const unsigned char ROOTDIR[]="\\";
76+
77+unsigned char * editormalloc(int size){
78+//配列RAM[]内にサイズsizeの領域を確保し、先頭アドレスを返す
79+//確保できない場合は、エラー表示し動作停止
80+ unsigned char *p;
81+ if(editormallocp+size>RAM+RAMSIZE){
82+ printstr("Cannot allocate memory");
83+ while(1) asm("wait");
84+ }
85+ p=editormallocp;
86+ editormallocp+=size;
87+ return p;
88+}
89+
90+void wait60thsec(unsigned short n){
91+ // 60分のn秒ウェイト(ビデオ画面の最下行信号出力終了まで待つ)
92+ n+=drawcount;
93+ while(drawcount!=n) asm(WAIT);
94+}
95+
96+unsigned int bpixtopos(_tbuf *bp,unsigned int ix){
97+// テキストバッファ上の位置からテキスト全体の先頭から何文字目かを返す
98+// bp:テキストバッファポインタ
99+// ix:bp->Bufの先頭からの文字数
100+ unsigned int pos;
101+ _tbuf *sbp;
102+ pos=0;
103+ sbp=TBufstart;
104+ while(sbp!=bp){
105+ pos+=sbp->n;
106+ sbp=sbp->next;
107+ if(sbp==NULL) return 0; //エラー
108+ }
109+ return pos+ix;
110+}
111+_tbuf * postobpix(int pos,unsigned short *pix){
112+// テキスト全体の先頭からpos文字目のテキストバッファ上の位置を返す
113+// 戻り値 テキストバッファポインタ
114+// *pix(戻り値):戻り値テキストバッファの先頭からの位置(ポインタ渡し)
115+ _tbuf *bp;
116+ bp=TBufstart;
117+ while(pos >= bp->n){
118+ if(bp->next==NULL) break; //全体最後尾の場合
119+ pos-=bp->n;
120+ bp=bp->next;
121+ }
122+ if(pos > bp->n){
123+ // オーバーランエラーの場合先頭を返す
124+ *pix=0;
125+ return TBufstart;
126+ }
127+ *pix=pos;
128+ return bp;
129+}
130+_tbuf * linetobpix(int line,unsigned short *pix){
131+// テキスト全体の先頭からline行目のテキストバッファ上の位置を返す
132+// 戻り値 テキストバッファポインタ
133+// *pix(戻り値):戻り値テキストバッファの先頭からの位置(ポインタ渡し)
134+ _tbuf *bp,*bp2;
135+ int ix,ix2;
136+ bp=TBufstart;
137+ bp2=TBufstart;
138+ ix=0;
139+ ix2=0;
140+ while(line>1){
141+ while(1){
142+ if(ix>=bp->n){
143+ if(bp->next==NULL) break;
144+ bp=bp->next;
145+ ix=0;
146+ continue;
147+ }
148+ if(bp->Buf[ix++] == '\n'){
149+ bp2=bp;
150+ ix2=ix;
151+ break;
152+ }
153+ }
154+ line--;
155+ }
156+ *pix=ix2;
157+ return bp2;
158+}
159+
160+_tbuf * newTBuf(_tbuf *prev){
161+// 新しいテキストバッファ1行を生成
162+// prev:挿入先の行(prevの後ろに追加)
163+// 戻り値 生成したバッファへのポインタ、生成できない場合NULL
164+ _tbuf *bp,*next;
165+
166+ //バッファの先頭から空きをサーチ
167+ bp=TextBuffer;
168+ while(1){
169+ if(bp->prev==NULL && bp!=TBufstart) break;
170+ bp++;
171+ if(bp>=TextBuffer+TBUFMAXLINE) return NULL;//最後まで空きなし
172+ }
173+ next=prev->next;
174+ //行挿入
175+ bp->prev=prev;
176+ bp->next=next;
177+ prev->next=bp;
178+ if(next!=NULL) next->prev=bp;
179+ bp->n=0;
180+ return bp;
181+}
182+
183+_tbuf * deleteTBuf(_tbuf *bp){
184+// テキストバッファの削除
185+// bp:削除する行のポインタ
186+// 戻り値 削除前の次のバッファへのポインタ、ない場合NULL
187+ unsigned short a,b;
188+ _tbuf *prev,*next;
189+ prev=bp->prev;
190+ next=bp->next;
191+ if(prev==NULL){
192+ //先頭行の場合
193+ if(next==NULL) return next; //最後の1行の場合は削除しない
194+ TBufstart=next; //次の行を先頭行設定
195+ }
196+ else prev->next=next; //前を次にリンク(最終行ならNULLがコピーされる)
197+ if(next!=NULL) next->prev=prev; //次があれば次を前にリンク
198+ bp->prev=NULL; //空きフラグ設定
199+ return next;
200+}
201+
202+// アンドゥバッファ
203+/*
204+UNDOBUFSIZEバイトの環状バッファ。テキストバッファに対する変更発生ごとに、
205+変更内容、変更場所をバッファの先頭に記録し、先頭位置を進める。
206+アンドゥ実行が呼び出されると、バッファ先頭から読み出し、テキストバッファに対して
207+元に戻す変更を行う。
208+バッファがいっぱいになると、最後尾から消去(上書き)していく。
209+
210+<バッファ仕様>
211+ 開始位置:テキストバッファトップから何バイト目か(2バイト。下位、上位の順)
212+ 繰り返し数:連続動作の場合の回数(2バイト。下位、上位の順)
213+ バッファの前からも後ろからも削除できるよう、先頭と最後に命令をおく。ただし、
214+ 後ろの命令コードが10以上の場合は削除された文字そのものを意味する。
215+1文字挿入
216+ UNDO_INSERT,開始位置,UNDO_INSERT
217+1文字上書き
218+ UNDO_OVERWRITE,開始位置,消去文字 [,消去文字が0?9の場合さらに0を付加]
219+1文字削除(Delete)
220+ UNDO_DELETE,開始位置,消去文字 [,消去文字が0?9の場合さらに0を付加]
221+1文字削除(BackSpace)
222+ UNDO_BACKSPACE,開始位置,消去文字 [,消去文字が0?9の場合さらに0を付加]
223+連続挿入(Ctrl+Vで貼り付け)
224+ UNDO_CONTINS,開始位置,繰り返し数,UNDO_CONTINS
225+連続削除(領域選択して削除)
226+ UNDO_CONTDEL,繰り返し数,消去文字列,開始位置,繰り返し数,UNDO_CONTDEL
227+*/
228+
229+void pushundomem(unsigned char c){
230+// アンドゥ用メモリの先頭に1バイトを貯める
231+// 空きがなくなった場合、最後尾の1命令分を無効化
232+ unsigned char *p;
233+ int n;
234+
235+ if(undobuf_used>=UNDOBUFSIZE){
236+ //空きがない場合、最後尾のブロックのバイト数分をバッファ利用済み量から減らす
237+ p=undobuf_top-undobuf_used; //最後尾
238+ if(p<undobuf) p+=UNDOBUFSIZE;
239+ switch(*p){
240+ case UNDO_INSERT: //1文字挿入
241+ undobuf_used-=4;
242+ break;
243+ case UNDO_OVERWRITE: //1文字上書き
244+ case UNDO_DELETE: //1文字削除
245+ case UNDO_BACKSPACE: //1文字削除(BS)
246+ undobuf_used-=4;
247+ p+=3;
248+ if(p>=undobuf+UNDOBUFSIZE) p-=UNDOBUFSIZE;
249+ if(*p<10) undobuf_used--; //コード0?9の場合後ろに0が付加されている
250+ break;
251+ case UNDO_CONTINS: //連続挿入
252+ undobuf_used-=6;
253+ break;
254+ case UNDO_CONTDEL: //連続削除
255+ //繰り返し数の読み出し
256+ p++;
257+ if(p>=undobuf+UNDOBUFSIZE) p-=UNDOBUFSIZE;
258+ n=*p++;
259+ if(p>=undobuf+UNDOBUFSIZE) p-=UNDOBUFSIZE;
260+ n+=*p<<8;
261+ undobuf_used-=n+8;
262+ break;
263+ }
264+ }
265+ //アンドゥバッファ先頭に1バイト挿入し、先頭位置を1進める
266+ *undobuf_top++=c;
267+ if(undobuf_top>=undobuf+UNDOBUFSIZE) undobuf_top-=UNDOBUFSIZE;
268+ undobuf_used++;
269+}
270+void pushundomem2(unsigned short w){
271+// アンドゥバッファに2バイト貯める、下位、上位の順
272+ pushundomem((unsigned char)w);
273+ pushundomem(w>>8);
274+}
275+unsigned char popundomem(){
276+// アンドゥバッファから1バイト読み出し、先頭を1つ戻す
277+// 戻り値:読み出したコード
278+ undobuf_top--;
279+ if(undobuf_top<undobuf) undobuf_top+=UNDOBUFSIZE;
280+ undobuf_used--;
281+ return *undobuf_top;
282+}
283+unsigned short popundomem2(){
284+// アンドゥバッファから2バイト読み出し
285+// 戻り値:読み出した2バイトコード
286+ unsigned short w;
287+ w=popundomem()<<8;
288+ w+=popundomem();
289+ return w;
290+}
291+void setundobuf(int com,_tbuf *bp,unsigned short ix,unsigned char c,unsigned short n){
292+//アンドゥバッファにデータをセットする
293+//com:コマンド 1:1文字削除、2:1文字上書き、3:1文字挿入、4:連続削除、5:連続挿入開始
294+//bp,ix:バッファ上の実行場所(カーソル位置)
295+//c:文字(上書き、挿入の場合のみ使用)
296+//n:連続数(連続の場合のみ使用)
297+ unsigned short pos;
298+
299+ pos=bpixtopos(bp,ix); //テキストバッファ先頭から何バイト目かを求める
300+ switch(com){
301+ case UNDO_INSERT: //1文字挿入
302+ pushundomem(com);
303+ pushundomem2(pos);
304+ pushundomem(com);
305+ break;
306+ case UNDO_OVERWRITE: //1文字上書き
307+ case UNDO_DELETE: //1文字削除(Delete)
308+ case UNDO_BACKSPACE: //1文字削除(BackSpace)
309+ pushundomem(com);
310+ pushundomem2(pos);
311+ pushundomem(c);
312+ if(c<10) pushundomem(0); //10未満のコードの場合0を付加
313+ break;
314+ case UNDO_CONTINS: //連続挿入
315+ pushundomem(com);
316+ pushundomem2(pos);
317+ pushundomem2(n);
318+ pushundomem(com);
319+ break;
320+ case UNDO_CONTDEL: //連続削除
321+ pushundomem(com);
322+ pushundomem2(n);
323+ break;
324+ }
325+}
326+
327+int insertchar(_tbuf *bp,unsigned int ix,unsigned char c,int undo){
328+//テキストバッファbpの先頭からixバイトの位置にcを挿入
329+//undo 0:通常(アンドゥバッファに格納する)、1:連続挿入中、2:アンドゥ中
330+//戻り値 成功:0、不正または容量オーバー:-1、空きがあるはずなのに失敗:1
331+ unsigned char *p;
332+
333+ if(ix > bp->n) return -1; //不正指定
334+ if(num >= TBUFMAXSIZE) return -1; //バッファ容量オーバー
335+ if(bp->n < TBUFSIZE){
336+ //ライン内だけで1バイト挿入可能//
337+ for(p=bp->Buf + bp->n ; p > bp->Buf+ix ; p--) *p=*(p-1);
338+ *p=c;
339+ if(!undo) setundobuf(UNDO_INSERT,bp,ix,0,0); //アンドゥバッファ設定
340+ bp->n++;
341+ num++; //バッファ使用量
342+// if(bp->n >= TBUFSIZE && bp->next==NULL) newTBuf(bp); //バッファがいっぱいになったら新たにバッファ生成
343+ return 0;
344+ }
345+ //ラインがあふれる場合
346+ if(bp->next==NULL || bp->next->n >=TBUFSIZE){
347+ // 最終行または次のラインバッファがいっぱいだったら一行挿入
348+ if(newTBuf(bp)==NULL){
349+ // ラインバッファ挿入不可
350+ return 1;
351+ }
352+ }
353+ if(ix==TBUFSIZE){
354+ insertchar(bp->next,0,c,undo);
355+ return 0;
356+ }
357+ p=bp->Buf + TBUFSIZE-1;
358+ insertchar(bp->next,0,*p,1); //次の行の先頭に1文字挿入(必ず空きあり)
359+ for( ; p > bp->Buf+ix ; p--) *p=*(p-1);
360+ *p=c;
361+ if(!undo) setundobuf(UNDO_INSERT,bp,ix,0,0); //アンドゥバッファ設定
362+ return 0;
363+}
364+
365+int overwritechar(_tbuf *bp,unsigned int ix,unsigned char c,int undo){
366+//テキストバッファbpの先頭からixバイトの位置をcで上書き
367+//undo 0:通常(アンドゥバッファに格納する)、1:連続中、2:アンドゥ中
368+//戻り値 成功:0、不正または容量オーバー:-1、空きがあるはずなのに失敗:1
369+
370+ //現在のバッファ位置の文字が終端または改行の場合、挿入モード
371+ if(ix > bp->n) return -1; //不正指定
372+ while(ix >= bp->n){
373+ if(bp->next==NULL){
374+ //テキスト全体最後尾の場合は挿入
375+ return insertchar(bp,ix,c,undo);
376+ }
377+ bp=bp->next;
378+ ix=0;
379+ }
380+ if(bp->Buf[ix]=='\n') return insertchar(bp,ix,c,undo);
381+ if(!undo) setundobuf(UNDO_OVERWRITE,bp,ix,bp->Buf[ix],0); //アンドゥバッファ設定
382+ bp->Buf[ix]=c;
383+ return 0;
384+}
385+
386+void deletechar(_tbuf *bp,unsigned int ix,int undo){
387+//テキストバッファbpの先頭からixバイトの位置の1バイト削除
388+//undo -1:通常BackSpace(アンドゥバッファに格納する)
389+// 0:通常DELETE(アンドゥバッファに格納する)、1:連続中、2:アンドゥ中
390+ unsigned char *p;
391+
392+ if(ix > bp->n) return; //不正指定
393+ if(ix !=bp->n){
394+ //バッファの最後の文字より後ろでない場合
395+
396+ //アンドゥバッファ設定
397+ if(undo==1) pushundomem(bp->Buf[ix]); //連続削除中
398+ else if(undo==-1) setundobuf(UNDO_BACKSPACE,bp,ix,bp->Buf[ix],0); //1文字削除(backspace)
399+ else if(undo==0) setundobuf(UNDO_DELETE,bp,ix,bp->Buf[ix],0); //1文字削除
400+
401+ for(p=bp->Buf+ix ; p< bp->Buf + bp->n-1 ; p++) *p=*(p+1);
402+ bp->n--;
403+ num--; //バッファ使用量
404+ return;
405+ }
406+ //行バッファの現在の最後の場合(削除する文字がない場合)
407+ if(bp->next==NULL) return; //全体の最後の場合、何もしない
408+ deletechar(bp->next,0,undo); //次の行の先頭文字を削除
409+}
410+int gabagecollect1(void){
411+//断片化されたテキストバッファの隙間を埋めるガベージコレクション
412+//カーソルの前と後ろそれぞれ探索して最初の1バイト分のみ実施
413+//戻り値 1バイトでも移動した場合:1、なかった場合:0
414+
415+ _tbuf *bp;
416+ int f=0;
417+ unsigned char *p,*p2;
418+
419+ //カーソルがバッファの先頭にある場合、前のバッファの最後尾に変更
420+ //(ただし前に空きがない場合と先頭バッファの場合を除く)
421+ while(cursorix==0 && cursorbp->prev!=NULL && cursorbp->prev->n <TBUFSIZE){
422+ cursorbp=cursorbp->prev;
423+ cursorix=cursorbp->n;
424+ }
425+ //画面左上位置がバッファの先頭にある場合、前のバッファの最後尾に変更
426+ //(ただし先頭バッファの場合を除く)
427+ while(disptopix==0 && disptopbp->prev!=NULL){
428+ disptopbp=disptopbp->prev;
429+ disptopix=disptopbp->n;
430+ }
431+ //カーソルのあるバッファ以外の空バッファを全て削除
432+ bp=TBufstart;
433+ while(bp!=NULL){
434+ if(bp->n == 0 && bp!=cursorbp){
435+ if(bp==disptopbp) disptopbp=bp->next; //画面左上位置が空バッファ先頭の場合、次にずらす
436+ bp=deleteTBuf(bp); //空きバッファ削除
437+ }
438+ else bp=bp->next;
439+ }
440+
441+ //カーソル位置より前の埋まっていないバッファを先頭からサーチ
442+ bp=TBufstart;
443+ while(bp->n >= TBUFSIZE){
444+ if(bp==cursorbp) break;
445+ bp=bp->next;
446+ }
447+ if(bp!=cursorbp){
448+ //最初に見つけた空き場所に次のバッファから1バイト移動
449+ bp->Buf[bp->n++] = bp->next->Buf[0];
450+ bp=bp->next;
451+ p=bp->Buf;
452+ p2=p+bp->n-1;
453+ for( ; p<p2 ; p++) *p=*(p+1);
454+ bp->n--;
455+ f=1;
456+ if(bp == disptopbp) disptopix--;
457+ if(bp == cursorbp) cursorix--;
458+// else if(bp->n == 0) deleteTBuf(bp);
459+ }
460+ if(cursorbp->next ==NULL) return f; //カーソル位置が最終バッファなら終了
461+ //カーソル位置の次のバッファから埋まっていないバッファをサーチ
462+ bp=cursorbp;
463+ do{
464+ bp=bp->next;
465+ if(bp->next ==NULL) return f; //最終バッファに到達なら終了
466+ } while(bp->n >=TBUFSIZE);
467+
468+ //最初に見つけた空き場所に次のバッファから1バイト移動
469+ bp->Buf[bp->n++] = bp->next->Buf[0];
470+ bp=bp->next;
471+ p=bp->Buf;
472+ p2=p+bp->n-1;
473+ for( ; p<p2 ; p++) *p=*(p+1);
474+ bp->n--;
475+ f=1;
476+ if(bp->n == 0) deleteTBuf(bp);
477+ return f;
478+}
479+void gabagecollect2(void){
480+// 変化がなくなるまで1バイト分のガベージコレクションを呼び出し
481+ while(gabagecollect1()) ;
482+}
483+void inittextbuf(void){
484+// テキストバッファの初期化
485+ _tbuf *bp;
486+ for(bp=TextBuffer;bp<TextBuffer+TBUFMAXLINE;bp++) bp->prev=NULL; //未使用バッファ化
487+ TBufstart=TextBuffer; //リンクの先頭設定
488+ TBufstart->next=NULL;
489+ TBufstart->n=0;
490+ num=0; //バッファ使用量
491+ edited=0; //編集済みフラグクリア
492+ undobuf_top=undobuf;
493+ undobuf_used=0;
494+}
495+void redraw(){
496+//画面の再描画
497+ unsigned char *vp;
498+ _tbuf *bp,*bp1,*bp2;
499+ int ix,ix1,ix2;
500+ int x,y;
501+ unsigned char ch,cl;
502+
503+ vp=TVRAM;
504+ bp=disptopbp;
505+ ix=disptopix;
506+ cl=COLOR_NORMALTEXT;
507+ if(cursorbp1==NULL){
508+ //範囲選択モードでない場合
509+ bp1=NULL;
510+ bp2=NULL;
511+ }
512+ else{
513+ //範囲選択モードの場合、開始位置と終了の前後判断して
514+ //bp1,ix1を開始位置、bp2,ix2を終了位置に設定
515+ if(cy<cy1 || (cy==cy1 && cx<cx1)){
516+ bp1=cursorbp;
517+ ix1=cursorix;
518+ bp2=cursorbp1;
519+ ix2=cursorix1;
520+ }
521+ else{
522+ bp1=cursorbp1;
523+ ix1=cursorix1;
524+ bp2=cursorbp;
525+ ix2=cursorix;
526+ }
527+ }
528+ for(y=0;y<EDITWIDTHY;y++){
529+ if(bp==NULL) break;
530+ for(x=0;x<twidth;x++){
531+ //文字がある位置までサーチ
532+ while(ix>=bp->n){
533+ if(bp==bp1 && ix==ix1) cl=COLOR_AREASELECTTEXT;
534+ if(bp==bp2 && ix==ix2) cl=COLOR_NORMALTEXT;
535+ bp=bp->next;
536+ ix=0;
537+ if(bp==NULL) break;
538+ }
539+ if(bp==NULL) break; //バッファ最終
540+ if(bp==bp1 && ix==ix1) cl=COLOR_AREASELECTTEXT;
541+ if(bp==bp2 && ix==ix2) cl=COLOR_NORMALTEXT;
542+ ch=bp->Buf[ix++];
543+ if(ch=='\n') break;
544+ if(twidth==30) *(vp+ATTROFFSET1)=cl;
545+ else *(vp+ATTROFFSET2)=cl;
546+ *vp++=ch;
547+ }
548+ //改行およびバッファ最終以降の右側表示消去
549+ if(twidth==30){
550+ for(;x<WIDTH_X1;x++){
551+ *(vp+ATTROFFSET1)=0;
552+ *vp++=0;
553+ }
554+ }
555+ else{
556+ for(;x<WIDTH_X2;x++){
557+ *(vp+ATTROFFSET2)=0;
558+ *vp++=0;
559+ }
560+ }
561+ }
562+ //バッファ最終以降の下側表示消去
563+ for(;y<EDITWIDTHY;y++){
564+ if(twidth==30){
565+ for(x=0;x<WIDTH_X1;x++){
566+ *(vp+ATTROFFSET1)=0;
567+ *vp++=0;
568+ }
569+ }
570+ else{
571+ for(x=0;x<WIDTH_X2;x++){
572+ *(vp+ATTROFFSET2)=0;
573+ *vp++=0;
574+ }
575+ }
576+ }
577+}
578+
579+void cursor_left(void){
580+//カーソルを1つ前に移動
581+//出力:下記変数を移動先の値に変更
582+//cursorbp,cursorix バッファ上のカーソル位置
583+//cx,cy 画面上のカーソル位置
584+//cx2 cxと同じ
585+//disptopbp,disptopix 画面左上のバッファ上の位置
586+
587+ _tbuf *bp;
588+ int ix;
589+ int i;
590+ int x;
591+
592+ //バッファ上のカーソル位置を1つ前に移動
593+ if(cursorix!=0) cursorix--;
594+ else while(1) {
595+ //1つ前のバッファの最後尾に移動、ただし空バッファは飛ばす
596+ if(cursorbp->prev==NULL) return; //テキスト全体先頭なので移動しない
597+ cursorbp=cursorbp->prev;
598+ if(cursorbp->n >0){
599+ cursorix=cursorbp->n-1;//バッファ最後尾
600+ break;
601+ }
602+ }
603+
604+ //カーソルおよび画面左上位置の更新
605+ if(cx>0){
606+ //左端でなければカーソルを単純に1つ左に移動して終了
607+ cx--;
608+ cx2=cx;
609+ return;
610+ }
611+ if(cy>0){
612+ //左端だが上端ではない場合
613+ if(cursorbp->Buf[cursorix]!='\n'){
614+ // 移動先が改行コードでない場合、カーソルは1つ上の行の右端に移動
615+ cx=twidth-1;
616+ cx2=cx;
617+ cy--;
618+ return;
619+ }
620+ //画面左上位置から最後尾のX座標をサーチ
621+ bp=disptopbp;
622+ ix=disptopix;
623+ x=0;
624+ while(ix!=cursorix || bp!=cursorbp){
625+ if(bp->n==0){
626+ //空バッファの場合次へ
627+ bp=bp->next;
628+ ix=0;
629+ continue;
630+ }
631+ if(bp->Buf[ix++]=='\n' || x>=twidth-1) x=0;
632+ else x++;
633+ if(ix >= bp->n){
634+ bp=bp->next;
635+ ix=0;
636+ }
637+ }
638+ cx=x;
639+ cx2=cx;
640+ cy--;
641+ line_no--;
642+ return;
643+ }
644+
645+ //左端かつ上端の場合
646+ if(cursorbp->Buf[cursorix]!='\n'){
647+ // 移動先が改行コードでない場合、カーソルは右端に移動
648+ // 画面左上位置は画面横幅分前に移動
649+ cx=twidth-1;
650+ cx2=cx;
651+ }
652+ else{
653+ //移動先が改行コードの場合
654+ //行頭(改行の次の文字またはバッファ先頭)と現在位置の文字数差を
655+ //画面横幅で割った余りがカーソルX座標
656+ bp=cursorbp;
657+ ix=cursorix;
658+ i=0;
659+ while(1){
660+ if(ix==0){
661+ if(bp->prev==NULL) break;
662+ bp=bp->prev;
663+ ix=bp->n;
664+ continue;
665+ }
666+ ix--;
667+ if(bp->Buf[ix]=='\n') break;
668+ i++;
669+ }
670+ cx=i % twidth;
671+ cx2=cx;
672+ line_no--;
673+ }
674+ //画面左上位置は現在位置からX座標分引いたところ
675+ bp=cursorbp;
676+ ix=cursorix;
677+ x=cx;
678+ while(x>0){
679+ if(ix==0){
680+ bp=bp->prev;
681+ ix=bp->n;
682+ continue;
683+ }
684+ ix--;
685+ x--;
686+ }
687+ disptopbp=bp;
688+ disptopix=ix;
689+}
690+void cursor_right(void){
691+//カーソルを1つ後ろに移動
692+//出力:下記変数を移動先の値に変更
693+//cursorbp,cursorix バッファ上のカーソル位置
694+//cx,cy 画面上のカーソル位置
695+//cx2 cxと同じ
696+//disptopbp,disptopix 画面左上のバッファ上の位置
697+
698+ _tbuf *bp;
699+ int ix;
700+ int i;
701+ int x;
702+ unsigned char c;
703+
704+ if(cursorix >= cursorbp->n){
705+ //バッファ最後尾の場合、次の先頭に移動
706+ bp=cursorbp;
707+ while(1) {
708+ //空バッファは飛ばす
709+ if(bp->next==NULL) return; //テキスト全体最後尾なので移動しない
710+ bp=bp->next;
711+ if(bp->n >0) break;
712+ }
713+ cursorbp=bp;
714+ cursorix=0;//バッファ先頭
715+ }
716+ c=cursorbp->Buf[cursorix++]; //バッファ上のカーソル位置のコードを読んで1つ後ろに移動
717+ if(c!='\n' && cx<twidth-1){
718+ //カーソル位置が改行でも右端でもない場合単純に1つ右に移動して終了
719+ cx++;
720+ cx2=cx;
721+ return;
722+ }
723+ cx=0; //カーソルを左端に移動
724+ cx2=cx;
725+ if(c=='\n') line_no++;
726+ if(cy<EDITWIDTHY-1){
727+ //下端でなければカーソルを次行に移動して終了
728+ cy++;
729+ return;
730+ }
731+ //下端の場合
732+ //画面左上位置を更新
733+ //改行コードまたは画面横幅超えるまでサーチ
734+ bp=disptopbp;
735+ ix=disptopix;
736+ x=0;
737+ while(x<twidth){
738+ if(ix >= bp->n){
739+ bp=bp->next;
740+ ix=0;
741+ continue;
742+ }
743+ if(bp->Buf[ix++]=='\n') break;
744+ x++;
745+ }
746+ disptopbp=bp;
747+ disptopix=ix;
748+}
749+void cursor_up(void){
750+//カーソルを1つ上に移動
751+//出力:下記変数を移動先の値に変更
752+//cursorbp,cursorix バッファ上のカーソル位置
753+//cx,cy 画面上のカーソル位置
754+//cx2 移動前のcxと同じ
755+//disptopbp,disptopix 画面左上のバッファ上の位置
756+
757+ _tbuf *bp;
758+ int ix;
759+ int i;
760+ int x;
761+ unsigned char c;
762+
763+ //画面幅分前に戻ったところがバッファ上カーソルの移動先
764+ //途中で改行コードがあれば別の手段で検索
765+ bp=cursorbp;
766+ ix=cursorix;
767+ i=cx2-cx;
768+ while(i<twidth){
769+ if(ix==0){
770+ if(bp->prev==NULL) return; //バッファ先頭までサーチしたら移動なし
771+ bp=bp->prev;
772+ ix=bp->n;
773+ continue;
774+ }
775+ ix--;
776+ if(bp->Buf[ix]=='\n') break;
777+ i++;
778+ }
779+ cursorbp=bp;
780+ cursorix=ix;
781+ //画面幅の間に改行コードがなかった場合
782+ if(i==twidth){
783+ cx=cx2;
784+ //画面上端でなければカーソルを1つ上に移動して終了
785+ if(cy>0){
786+ cy--;
787+ return;
788+ }
789+ //画面上端の場合、カーソル位置からX座標分戻ったところが画面左上位置
790+ x=cx;
791+ while(x>0){
792+ if(ix==0){
793+ bp=bp->prev;
794+ ix=bp->n;
795+ continue;
796+ }
797+ ix--;
798+ x--;
799+ }
800+ disptopbp=bp;
801+ disptopix=ix;
802+ return;
803+ }
804+ //改行が見つかった場合
805+ //行頭(改行の次の文字またはバッファ先頭)と現在位置の文字数差を
806+ //画面横幅で割った余りを求める
807+ line_no--;
808+ i=0;
809+ while(1){
810+ if(ix==0){
811+ if(bp->prev==NULL) break;
812+ bp=bp->prev;
813+ ix=bp->n;
814+ continue;
815+ }
816+ ix--;
817+ if(bp->Buf[ix]=='\n') break;
818+ i++;
819+ }
820+ x=i % twidth; //改行ブロックの最終行の右端
821+ bp=cursorbp;
822+ ix=cursorix;
823+ //バッファ上のカーソル位置は改行ブロックの最終行右端からカーソルX座標分戻る
824+ //最終行右端のほうが小さい場合、その場所をバッファ上のカーソル位置とする
825+ while(x>cx2){
826+ if(ix==0){
827+ bp=bp->prev;
828+ ix=bp->n;
829+ continue;
830+ }
831+ ix--;
832+ x--;
833+ }
834+ cursorbp=bp;
835+ cursorix=ix;
836+ cx=x; //cx2または改行ブロック最終行右端
837+ if(cy>0){
838+ //画面上端でなければカーソルを1つ上に移動して終了
839+ cy--;
840+ return;
841+ }
842+ //画面上端の場合
843+ //画面左上位置は現在位置からX座標分引いたところ
844+ while(x>0){
845+ if(ix==0){
846+ bp=bp->prev;
847+ ix=bp->n;
848+ continue;
849+ }
850+ ix--;
851+ x--;
852+ }
853+ disptopbp=bp;
854+ disptopix=ix;
855+}
856+void cursor_down(void){
857+//カーソルを1つ下に移動
858+//出力:下記変数を移動先の値に変更
859+//cursorbp,cursorix バッファ上のカーソル位置
860+//cx,cy 画面上のカーソル位置
861+//cx2 移動前のcxと同じ
862+//disptopbp,disptopix 画面左上のバッファ上の位置
863+
864+ _tbuf *bp;
865+ int ix;
866+ int x;
867+ unsigned char c;
868+
869+ //次行の先頭サーチ
870+ //カーソル位置から画面右端までの間に改行コードがあれば次の文字が先頭
871+ bp=cursorbp;
872+ ix=cursorix;
873+ x=cx;
874+ while(x<twidth){
875+ if(ix>=bp->n){
876+ if(bp->next==NULL) return; //バッファ最後までサーチしたら移動なし
877+ bp=bp->next;
878+ ix=0;
879+ continue;
880+ }
881+ c=bp->Buf[ix];
882+ ix++;
883+ x++;
884+ if(c=='\n'){
885+ line_no++;
886+ break;
887+ }
888+ }
889+ //次行先頭からcx2文字数分後ろにサーチ
890+ x=0;
891+ while(x<cx2){
892+ if(ix>=bp->n){
893+ if(bp->next==NULL) break; //バッファ最後の場合そこに移動
894+ bp=bp->next;
895+ ix=0;
896+ continue;
897+ }
898+ if(bp->Buf[ix]=='\n') break; //改行コードの場合そこに移動
899+ ix++;
900+ x++;
901+ }
902+ cursorbp=bp;
903+ cursorix=ix;
904+ cx=x;
905+ //画面下端でなければカーソルを1つ下に移動して終了
906+ if(cy<EDITWIDTHY-1){
907+ cy++;
908+ return;
909+ }
910+ //下端の場合
911+ //画面左上位置を更新
912+ //改行コードまたは画面横幅超えるまでサーチ
913+ bp=disptopbp;
914+ ix=disptopix;
915+ x=0;
916+ while(x<twidth){
917+ if(ix >= bp->n){
918+ bp=bp->next;
919+ ix=0;
920+ continue;
921+ }
922+ if(bp->Buf[ix++]=='\n') break;
923+ x++;
924+ }
925+ disptopbp=bp;
926+ disptopix=ix;
927+}
928+void cursor_home(void){
929+//カーソルを行先頭に移動
930+//出力:下記変数を移動先の値に変更
931+//cursorbp,cursorix バッファ上のカーソル位置
932+//cx,cx2 0
933+//cy 変更なし
934+//disptopbp,disptopix 画面左上のバッファ上の位置(変更なし)
935+
936+ //カーソルX座標分前に移動
937+ while(cx>0){
938+ if(cursorix==0){
939+ //空バッファは飛ばす
940+ cursorbp=cursorbp->prev;
941+ cursorix=cursorbp->n;
942+ continue;
943+ }
944+ cursorix--;
945+ cx--;
946+ }
947+ cx2=0;
948+}
949+void cursor_end(void){
950+//カーソルを行末に移動
951+//出力:下記変数を移動先の値に変更
952+//cursorbp,cursorix バッファ上のカーソル位置
953+//cx,cx2 行末
954+//cy 変更なし
955+//disptopbp,disptopix 画面左上のバッファ上の位置(変更なし)
956+
957+ //カーソルX座標を画面幅分後ろに移動
958+ //改行コードまたはバッファ最終があればそこに移動
959+ while(cx<twidth-1){
960+ if(cursorix>=cursorbp->n){
961+ //空バッファは飛ばす
962+ if(cursorbp->next==NULL) break;
963+ cursorbp=cursorbp->next;
964+ cursorix=0;
965+ continue;
966+ }
967+ if(cursorbp->Buf[cursorix]=='\n') break;
968+ cursorix++;
969+ cx++;
970+ }
971+ cx2=cx;
972+}
973+void cursor_pageup(void){
974+//PageUpキー
975+//最上行が最下行になるまでスクロール
976+//出力:下記変数を移動先の値に変更
977+//cursorbp,cursorix バッファ上のカーソル位置
978+//cx,cx2
979+//cy
980+//disptopbp,disptopix 画面左上のバッファ上の位置
981+
982+ _tbuf *bp;
983+ int ix;
984+ int i;
985+ int cy_old;
986+
987+ cy_old=cy;
988+ while(cy>0) cursor_up(); // cy==0になるまでカーソルを上に移動
989+ for(i=0;i<EDITWIDTHY-1;i++){
990+ //画面行数-1行分カーソルを上に移動
991+ bp=disptopbp;
992+ ix=disptopix;
993+ cursor_up();
994+ if(bp==disptopbp && ix==disptopix) break; //最上行で移動できなかった場合抜ける
995+ }
996+ //元のY座標までカーソルを下に移動、1行も動かなかった場合は最上行に留まる
997+ if(i>0) while(cy<cy_old) cursor_down();
998+}
999+void cursor_pagedown(void){
1000+//PageDownキー
1001+//最下行が最上行になるまでスクロール
1002+//出力:下記変数を移動先の値に変更
1003+//cursorbp,cursorix バッファ上のカーソル位置
1004+//cx,cx2
1005+//cy
1006+//disptopbp,disptopix 画面左上のバッファ上の位置
1007+
1008+ _tbuf *bp;
1009+ int ix;
1010+ int i;
1011+ int y;
1012+ int cy_old;
1013+
1014+ cy_old=cy;
1015+ while(cy<EDITWIDTHY-1){
1016+ // cy==EDITWIDTH-1になるまでカーソルを下に移動
1017+ y=cy;
1018+ cursor_down();
1019+ if(y==cy) break;// バッファ最下行で移動できなかった場合抜ける
1020+ }
1021+ for(i=0;i<EDITWIDTHY-1;i++){
1022+ //画面行数-1行分カーソルを下に移動
1023+ bp=disptopbp;
1024+ ix=disptopix;
1025+ cursor_down();
1026+ if(bp==disptopbp && ix==disptopix) break; //最下行で移動できなかった場合抜ける
1027+ }
1028+ //下端からさらに移動した行数分、カーソルを上に移動、1行も動かなかった場合は最下行に留まる
1029+ if(i>0) while(cy>cy_old) cursor_up();
1030+}
1031+void cursor_top(void){
1032+//カーソルをテキストバッファの先頭に移動
1033+ cursorbp=TBufstart;
1034+ cursorix=0;
1035+ cursorbp1=NULL; //範囲選択モード解除
1036+ disptopbp=cursorbp;
1037+ disptopix=cursorix;
1038+ cx=0;
1039+ cx2=0;
1040+ cy=0;
1041+ line_no=1;
1042+}
1043+
1044+int countarea(void){
1045+//テキストバッファの指定範囲の文字数をカウント
1046+//範囲は(cursorbp,cursorix)と(cursorbp1,cursorix1)で指定
1047+//後ろ側の一つ前の文字までをカウント
1048+ _tbuf *bp1,*bp2;
1049+ int ix1,ix2;
1050+ int n;
1051+
1052+ //範囲選択モードの場合、開始位置と終了の前後判断して
1053+ //bp1,ix1を開始位置、bp2,ix2を終了位置に設定
1054+ if(cy<cy1 || (cy==cy1 && cx<cx1)){
1055+ bp1=cursorbp;
1056+ ix1=cursorix;
1057+ bp2=cursorbp1;
1058+ ix2=cursorix1;
1059+ }
1060+ else{
1061+ bp1=cursorbp1;
1062+ ix1=cursorix1;
1063+ bp2=cursorbp;
1064+ ix2=cursorix;
1065+ }
1066+ n=0;
1067+ while(1){
1068+ if(bp1==bp2 && ix1==ix2) return n;
1069+ if(ix1 < bp1->n){
1070+ n++;
1071+ ix1++;
1072+ }
1073+ else{
1074+ bp1=bp1->next;
1075+ ix1=0;
1076+ }
1077+ }
1078+}
1079+void deletearea_len(_tbuf *bp,unsigned int ix,int n,int undo){
1080+//テキストバッファの指定位置から複数文字削除
1081+//bp,ix:削除開始位置
1082+//n:削除する文字数
1083+//undo:0:通常、2:アンドゥ中
1084+ unsigned char *p;
1085+ int i;
1086+
1087+ //選択範囲が最初のバッファの最後まである場合
1088+ if(n>=(bp->n - ix)){
1089+ if(!undo){
1090+ p=bp->Buf+ix;
1091+ for(i=ix;i < bp->n;i++) pushundomem(*p++); //アンドゥバッファに格納
1092+ }
1093+ n -= bp->n - ix; //削除文字数減
1094+ num-=bp->n - ix; //バッファ使用量を減数
1095+ bp->n=ix; //ix以降を削除
1096+ bp=bp->next;
1097+ if(bp==NULL) return;
1098+ ix=0;
1099+ }
1100+ //次のバッファ以降、選択範囲の終了位置が含まれないバッファは削除
1101+ while(n>=bp->n){
1102+ if(!undo){
1103+ p=bp->Buf;
1104+ for(i=0;i < bp->n;i++) pushundomem(*p++); //アンドゥバッファに格納
1105+ }
1106+ n-=bp->n; //削除文字数減
1107+ num-=bp->n; //バッファ使用量を減数
1108+ bp=deleteTBuf(bp); //バッファ削除して次のバッファに進む
1109+ if(bp==NULL) return;
1110+ }
1111+ //選択範囲の終了位置を含む場合、1文字ずつ削除
1112+ if(!undo) undo=1;
1113+ while(n>0){
1114+ deletechar(bp,ix,undo); //バッファから1文字削除(numは関数内で1減される)
1115+ n--;
1116+ }
1117+}
1118+void deletearea(void){
1119+//テキストバッファの指定範囲を削除
1120+//範囲は(cursorbp,cursorix)と(cursorbp1,cursorix1)で指定
1121+//後ろ側の一つ前の文字までを削除
1122+//削除後のカーソル位置は選択範囲の先頭にし、範囲選択モード解除する
1123+
1124+ _tbuf *bp;
1125+ int ix;
1126+ int n;
1127+
1128+ n=countarea(); //選択範囲の文字数カウント
1129+ if(n==0) return;
1130+
1131+ //範囲選択の開始位置と終了位置の前後を判断してカーソルを開始位置に設定
1132+ if(cy>cy1 || (cy==cy1 && cx>cx1)){
1133+ cursorbp=cursorbp1;
1134+ cursorix=cursorix1;
1135+ cx=cx1;
1136+ cy=cy1;
1137+ line_no=line_no1;
1138+ }
1139+ cx2=cx;
1140+ cursorbp1=NULL; //範囲選択モード解除
1141+
1142+ //bp,ixを開始位置に設定
1143+ bp=cursorbp;
1144+ ix=cursorix;
1145+
1146+ setundobuf(UNDO_CONTDEL,bp,ix,0,n); //アンドゥバッファ設定(連続削除開始)
1147+ deletearea_len(bp,ix,n,0); //n文字分削除
1148+ //アンドゥバッファに連続削除終了設定
1149+ pushundomem2(bpixtopos(bp,ix));
1150+ pushundomem2(n);
1151+ pushundomem(UNDO_CONTDEL);
1152+}
1153+void clipcopy(void){
1154+// 選択範囲をクリップボードにコピー
1155+ _tbuf *bp1,*bp2;
1156+ int ix1,ix2;
1157+ char *ps,*pd;
1158+
1159+ //範囲選択モードの場合、開始位置と終了の前後判断して
1160+ //bp1,ix1を開始位置、bp2,ix2を終了位置に設定
1161+ if(cy<cy1 || (cy==cy1 && cx<cx1)){
1162+ bp1=cursorbp;
1163+ ix1=cursorix;
1164+ bp2=cursorbp1;
1165+ ix2=cursorix1;
1166+ }
1167+ else{
1168+ bp1=cursorbp1;
1169+ ix1=cursorix1;
1170+ bp2=cursorbp;
1171+ ix2=cursorix;
1172+ }
1173+ ps=bp1->Buf+ix1;
1174+ pd=clipboard;
1175+ clipsize=0;
1176+ while(bp1!=bp2 || ix1!=ix2){
1177+ if(ix1 < bp1->n){
1178+ *pd++=*ps++;
1179+ clipsize++;
1180+ ix1++;
1181+ }
1182+ else{
1183+ bp1=bp1->next;
1184+ ps=bp1->Buf;
1185+ ix1=0;
1186+ }
1187+ }
1188+}
1189+void clippaste(void){
1190+// クリップボードから貼り付け
1191+ int n,i;
1192+ unsigned char *p;
1193+
1194+ if(clipsize==0 || num+clipsize>TBUFMAXSIZE) return;
1195+ setundobuf(UNDO_CONTINS,cursorbp,cursorix,0,clipsize); //アンドゥバッファ設定
1196+ p=clipboard;
1197+ for(n=clipsize;n>0;n--){
1198+ i=insertchar(cursorbp,cursorix,*p,1);
1199+ if(i>0){
1200+ //バッファ空きがあるのに挿入失敗の場合
1201+ gabagecollect2(); //全体ガベージコレクション
1202+ i=insertchar(cursorbp,cursorix,*p,1);//テキストバッファに1文字挿入
1203+ }
1204+ if(i!=0) break;//挿入失敗
1205+ cursor_right();//画面上、バッファ上のカーソル位置を1つ後ろに移動
1206+ p++;
1207+ }
1208+}
1209+void movecursor(int pos){
1210+// カーソルを現在の位置から任意の位置に移動
1211+// pos:移動したいテキストバッファ先頭からのバイト位置
1212+ int pos2,d;
1213+ pos2=bpixtopos(cursorbp,cursorix);
1214+ d=pos-pos2;
1215+ if(d==0) return;
1216+ if(d>0){
1217+ while(d>0){
1218+ cursor_right();
1219+ d--;
1220+ }
1221+ }
1222+ else{
1223+ while(d<0){
1224+ cursor_left();
1225+ d++;
1226+ }
1227+ }
1228+}
1229+void undoexec(){
1230+//アンドゥ実行
1231+ unsigned char c,c1;
1232+ _tbuf *bp;
1233+ unsigned short n,ix;
1234+ int pos;
1235+
1236+ if(undobuf_used==0) return; //アンドゥバッファ空
1237+ cursorbp1=NULL; //範囲選択解除
1238+ c=popundomem(); //アンドゥバッファ先頭の命令読み出し
1239+ switch(c){
1240+ case UNDO_INSERT: //1文字挿入
1241+ //カーソル移動し1文字削除
1242+ pos=popundomem2();
1243+ movecursor(pos);
1244+ bp=postobpix(pos,&ix);
1245+ deletechar(bp,ix,2);
1246+ popundomem(); //dummy read
1247+ break;
1248+ case UNDO_CONTINS: //連続挿入
1249+ //カーソル移動し連続数分削除
1250+ n=popundomem2();
1251+ pos=popundomem2();
1252+ movecursor(pos);
1253+ bp=postobpix(pos,&ix);
1254+ deletearea_len(bp,ix,n,2);
1255+ popundomem(); //dummy read
1256+ break;
1257+ case UNDO_CONTDEL: //連続削除
1258+ //カーソル移動し連続数分、コードを読み出して挿入
1259+ n=popundomem2();
1260+ pos=popundomem2();
1261+ movecursor(pos);
1262+ bp=postobpix(pos,&ix);
1263+ while(n>0){
1264+ insertchar(bp,ix,popundomem(),2);
1265+ n--;
1266+ }
1267+ popundomem2(); //dummy read
1268+ popundomem(); //dummy read
1269+ break;
1270+ case 0: //0の場合、次の1バイトが実際の有効なコード
1271+ c=popundomem();
1272+ default: //1文字削除(DEL、BS)、1文字上書き
1273+ //カーソル移動し1文字挿入(または上書き)
1274+ pos=popundomem2();
1275+ movecursor(pos);
1276+ bp=postobpix(pos,&ix);
1277+ c1=popundomem();
1278+ if(c1==UNDO_OVERWRITE){
1279+ overwritechar(bp,ix,c,2);
1280+ }
1281+ else{
1282+ insertchar(bp,ix,c,2);
1283+ if(c1==UNDO_BACKSPACE) cursor_right();
1284+ }
1285+ break;
1286+ }
1287+}
1288+
1289+void set_areamode(){
1290+//範囲選択モード開始時のカーソル開始位置グローバル変数設定
1291+ cursorbp1=cursorbp;
1292+ cursorix1=cursorix;
1293+ cx1=cx;
1294+ cy1=cy;
1295+ line_no1=line_no;
1296+}
1297+void save_cursor(void){
1298+//カーソル関連グローバル変数を一時避難
1299+ cursorbp_t=cursorbp;
1300+ cursorix_t=cursorix;
1301+ disptopbp_t=disptopbp;
1302+ disptopix_t=disptopix;
1303+ cx_t=cx;
1304+ cy_t=cy;
1305+ line_no_t=line_no;
1306+}
1307+void restore_cursor(void){
1308+//カーソル関連グローバル変数を一時避難場所から戻す
1309+ cursorbp=cursorbp_t;
1310+ cursorix=cursorix_t;
1311+ disptopbp=disptopbp_t;
1312+ disptopix=disptopix_t;
1313+ cx=cx_t;
1314+ cy=cy_t;
1315+ line_no=line_no_t;
1316+}
1317+
1318+int filesystemretry(){
1319+// SDファイルシステムの再初期化確認と実施
1320+// SDファイルへの保存や読み込み時にファイルエラーが発生した場合に呼び出す
1321+// 戻り値 0:初期化成功、-1:成功することなくEscapeで抜けた
1322+ unsigned short vk;
1323+ while(1){
1324+ setcursorcolor(COLOR_NORMALTEXT);
1325+ printstr((unsigned char *)Message3); //Retry / Quit
1326+ while(1){
1327+ inputchar(); //1文字入力待ち
1328+ vk=vkey & 0xff;
1329+ if(vk==VK_RETURN || vk==VK_SEPARATOR) break;
1330+ if(vk==VK_ESCAPE) return -1;
1331+ }
1332+ //ファイルシステム初期化
1333+ if(FSInit()!=FALSE) return 0; //成功
1334+ //エラーの場合
1335+ setcursorcolor(COLOR_ERRORTEXT);
1336+ printstr((unsigned char *)Message2);//File System Error
1337+ }
1338+}
1339+
1340+int sdfilecopy(char *sourcefile,char *distfile){
1341+// SDカード上のファイルをコピー
1342+// soucefile:コピー元ファイル名
1343+// distfile:コピー先ファイル名
1344+// 戻り値:正常終了 0、エラー終了時エラー番号
1345+ FSFILE *sfp,*dfp;
1346+ int n,er,c;
1347+ er=0;
1348+ sfp=FSfopen(sourcefile,"r");
1349+ if(sfp==NULL) return ERR_CANTFILEOPEN;
1350+ dfp=FSfopen(distfile,"w");
1351+ if(dfp==NULL){
1352+ FSfclose(sfp);
1353+ return ERR_CANTFILEOPEN;
1354+ }
1355+ c=0;
1356+ while(1){
1357+ if(c==0){
1358+ printchar('.');
1359+ c=100;
1360+ }
1361+ c--;
1362+ n=FSfread(filebuf,1,FILEBUFSIZE,sfp);
1363+ if(n==0) break;
1364+ if(FSfwrite(filebuf,1,n,dfp)!=n){
1365+ er=ERR_CANTWRITEFILE;
1366+ break;
1367+ }
1368+ }
1369+ FSfclose(sfp);
1370+ FSfclose(dfp);
1371+ return er;
1372+}
1373+int savetextfile(char *filename){
1374+// テキストバッファをテキストファイルに書き込み
1375+// 書き込み成功で0、失敗でエラーコード(負数)を返す
1376+ FSFILE *fp;
1377+ _tbuf *bp;
1378+ int ix,n,i,er;
1379+ unsigned char *ps,*pd;
1380+ er=0;//エラーコード
1381+ i=-1;
1382+ fp=FSfopen(filename,"w");
1383+ if(fp==NULL) return ERR_CANTFILEOPEN;
1384+ bp=TBufstart;
1385+ ix=0;
1386+ ps=bp->Buf;
1387+ do{
1388+ pd=filebuf;
1389+ n=0;
1390+ while(n<FILEBUFSIZE-1){
1391+ //改行コードが2バイトになることを考慮してバッファサイズ-1までとする
1392+ while(ix>=bp->n){
1393+ bp=bp->next;
1394+ if(bp==NULL){
1395+ break;
1396+ }
1397+ ix=0;
1398+ ps=bp->Buf;
1399+ }
1400+ if(bp==NULL) break;
1401+ if(*ps=='\n'){
1402+ *pd++='\r'; //改行コード0A→0D 0Aにする
1403+ n++;
1404+ }
1405+ *pd++=*ps++;
1406+ ix++;
1407+ n++;
1408+ }
1409+ if(n>0){
1410+ i=FSfwrite(filebuf,1,n,fp);
1411+ if(i!=n) er=ERR_CANTWRITEFILE;
1412+ }
1413+ } while(bp!=NULL && er==0);
1414+ FSfclose(fp);
1415+ return er;
1416+}
1417+int loadtextfile(char *filename){
1418+// テキストファイルをテキストバッファに読み込み
1419+// 読み込み成功で0、失敗でエラーコード(負数)を返す
1420+ FSFILE *fp;
1421+ _tbuf *bp;
1422+ int ix,n,i,er;
1423+ unsigned char *ps,*pd;
1424+ er=0;//エラーコード
1425+ fp=FSfopen(filename,"r");
1426+ if(fp==NULL) return ERR_CANTFILEOPEN;
1427+ inittextbuf();
1428+ bp=TextBuffer;
1429+ ix=0;
1430+ pd=bp->Buf;
1431+ do{
1432+ n=FSfread(filebuf,1,FILEBUFSIZE,fp);
1433+ ps=filebuf;
1434+ for(i=0;i<n;i++){
1435+ if(ix>=TBUFSIZE){
1436+ bp->n=TBUFSIZE;
1437+ bp=newTBuf(bp);
1438+ if(bp==NULL){
1439+ er=ERR_FILETOOBIG;
1440+ break;
1441+ }
1442+ ix=0;
1443+ pd=bp->Buf;
1444+ }
1445+ if(*ps=='\r') ps++; //改行コード0D 0A→0Aにする(単純に0D無視)
1446+ else{
1447+ *pd++=*ps++;
1448+ ix++;
1449+ num++;//バッファ総文字数
1450+ if(num>TBUFMAXSIZE){
1451+ er=ERR_FILETOOBIG;
1452+ break;
1453+ }
1454+ }
1455+ }
1456+ } while(n==FILEBUFSIZE && er==0);
1457+ if(bp!=NULL) bp->n=ix;//最後のバッファの文字数
1458+ FSfclose(fp);
1459+ if(er){
1460+ //エラー発生の場合バッファ、カーソル位置初期化
1461+ inittextbuf();
1462+ cursor_top();
1463+ }
1464+ return er;
1465+}
1466+int overwritecheck(char *fn){
1467+// ファイルの上書き確認
1468+// ファイルの存在をチェックし、存在する場合キーボードから上書き確認する
1469+// fn:ファイル名へのポインタ
1470+// 戻り値 0:存在しないまたは上書き、-1:上書きしない
1471+ SearchRec sr;
1472+ unsigned short vk;
1473+ if(FindFirst(fn,ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_ARCHIVE,&sr)) return 0; //ファイルが存在しない
1474+ setcursorcolor(COLOR_ERRORTEXT);
1475+ printstr(fn);
1476+ printstr(": File Exists\n");
1477+ setcursorcolor(COLOR_NORMALTEXT);
1478+ printstr("Ovewrite:[Enter] / Stop:[ESC]\n");
1479+ while(1){
1480+ inputchar(); //1文字入力待ち
1481+ vk=vkey & 0xff;
1482+ if(vk==VK_RETURN || vk==VK_SEPARATOR) return 0;
1483+ if(vk==VK_ESCAPE) return -1;
1484+ }
1485+}
1486+void printfilename(unsigned char x,unsigned char y,int f,int num_dir){
1487+// x,yの位置にファイル名またはディレクトリ名を表示
1488+
1489+ if(f==-2){
1490+ setcursor(x,y,COLOR_ERRORTEXT);
1491+ printchar('<');
1492+ printstr("New FILE");
1493+ printchar('>');
1494+ }
1495+ else if(f==-1){
1496+ setcursor(x,y,COLOR_ERRORTEXT);
1497+ printchar('<');
1498+ printstr("New Dir");
1499+ printchar('>');
1500+ }
1501+ else if(f<num_dir){
1502+ setcursor(x,y,COLOR_DIR);
1503+ printchar('[');
1504+ printstr(filenames[f]);
1505+ printchar(']');
1506+ }
1507+ else{
1508+ setcursor(x,y,COLOR_NORMALTEXT);
1509+ printstr(filenames[f]);
1510+ }
1511+}
1512+int select_dir_file(int filenum,int num_dir, unsigned char* msg){
1513+// filenames[]配列に読み込まれたファイルまたはディレクトリを画面表示しキーボードで選択する
1514+// filenum:ファイル+ディレクトリ数
1515+// num_dir:ディレクトリ数(filenames[]は先頭からnum_dir-1までがディレクトリ)
1516+// msg:画面上部に表示するメッセージ
1517+// 戻り値
1518+// filenames[]の選択されたファイルまたはディレクトリ番号
1519+// -1:新規ディレクトリ作成、tempfile[]にディレクトリ名
1520+// -2:新規ファイル作成、tempfile[]にファイル名
1521+// -3:ESCキーが押された
1522+ int top,f;
1523+ unsigned char *ps,*pd;
1524+ int x,y;
1525+ unsigned char vk;
1526+ //ファイル一覧を画面に表示
1527+ cls();
1528+ setcursor(0,0,COLOR_NORMALTEXT);
1529+ printstr(msg);
1530+ printstr(": ");
1531+ setcursorcolor(4);
1532+ printstr("Select&[Enter] / [ESC]\n");
1533+ for(f=-2;f<filenum;f++){
1534+ x=(f&1)*15+1;
1535+ y=(f+2)/2+1;
1536+ if(y>=WIDTH_Y-1) break;
1537+ printfilename(x,y,f,num_dir);
1538+ }
1539+ top=-2;//画面一番先頭のファイル番号
1540+ f=-2;//現在選択中のファイル番号
1541+ while(1){
1542+ setcursor((f&1)*15,(f-top)/2+1,5);
1543+ printchar(0x1c);// Right Arrow
1544+ cursor--;
1545+ while(1){
1546+ inputchar();
1547+ vk=vkey & 0xff;
1548+ if(vk) break;
1549+ }
1550+ printchar(' ');
1551+ setcursor(0,WIDTH_Y-1,COLOR_NORMALTEXT);
1552+ for(x=0;x<twidth-1;x++) printchar(' '); //最下行のステータス表示を消去
1553+ switch(vk){
1554+ case VK_UP:
1555+ case VK_NUMPAD8:
1556+ //上矢印キー
1557+ if(f>=0){
1558+ f-=2;
1559+ if(f<top){
1560+ //画面最上部の場合、下にスクロールして最上部にファイル名2つ表示
1561+ if(twidth==WIDTH_X1){
1562+ setcursor(WIDTH_X1-1,WIDTH_Y-2,COLOR_NORMALTEXT);
1563+ while(cursor>=TVRAM+WIDTH_X1*2){
1564+ *cursor=*(cursor-WIDTH_X1);
1565+ *(cursor+ATTROFFSET1)=*(cursor+ATTROFFSET1-WIDTH_X1);
1566+ cursor--;
1567+ }
1568+ while(cursor>=TVRAM+WIDTH_X1) *cursor--=' ';
1569+ }
1570+ else{
1571+ setcursor(WIDTH_X2-1,WIDTH_Y-2,COLOR_NORMALTEXT);
1572+ while(cursor>=TVRAM+WIDTH_X2*2){
1573+ *cursor=*(cursor-WIDTH_X2);
1574+ *(cursor+ATTROFFSET2)=*(cursor+ATTROFFSET2-WIDTH_X2);
1575+ cursor--;
1576+ }
1577+ while(cursor>=TVRAM+WIDTH_X2) *cursor--=' ';
1578+ }
1579+ top-=2;
1580+ printfilename(1,1,top,num_dir);
1581+ printfilename(16,1,top+1,num_dir);
1582+ }
1583+ }
1584+ break;
1585+ case VK_DOWN:
1586+ case VK_NUMPAD2:
1587+ //下矢印キー
1588+ if(((f+2)&0xfffe)<filenum){
1589+ f+=2;
1590+ if(f>=filenum) f--;
1591+ if(f-top>=(WIDTH_Y-2)*2){
1592+ //画面最下部の場合、上にスクロールして最下部にファイル名1つor2つ表示
1593+ setcursor(0,1,COLOR_NORMALTEXT);
1594+ if(twidth==WIDTH_X1){
1595+ while(cursor<TVRAM+WIDTH_X1*(WIDTH_Y-2)){
1596+ *cursor=*(cursor+WIDTH_X1);
1597+ *(cursor+ATTROFFSET1)=*(cursor+ATTROFFSET1+WIDTH_X1);
1598+ cursor++;
1599+ }
1600+ while(cursor<TVRAM+WIDTH_X1*(WIDTH_Y-1)) *cursor++=' ';
1601+ }
1602+ else{
1603+ while(cursor<TVRAM+WIDTH_X2*(WIDTH_Y-2)){
1604+ *cursor=*(cursor+WIDTH_X2);
1605+ *(cursor+ATTROFFSET2)=*(cursor+ATTROFFSET2+WIDTH_X2);
1606+ cursor++;
1607+ }
1608+ while(cursor<TVRAM+WIDTH_X2*(WIDTH_Y-1)) *cursor++=' ';
1609+ }
1610+ top+=2;
1611+ printfilename(1,WIDTH_Y-2,f&0xfffe,num_dir);
1612+ if((f|1)<filenum){
1613+ printfilename(16,WIDTH_Y-2,f|1,num_dir);
1614+ }
1615+ }
1616+ }
1617+ break;
1618+ case VK_LEFT:
1619+ case VK_NUMPAD4:
1620+ //左矢印キー
1621+ if(f&1) f--;
1622+ break;
1623+ case VK_RIGHT:
1624+ case VK_NUMPAD6:
1625+ //右矢印キー
1626+ if((f&1)==0 && f+1<filenum) f++;
1627+ break;
1628+ case VK_RETURN: //Enterキー
1629+ case VK_SEPARATOR: //テンキーのEnter
1630+ if(f==-2){
1631+ //新規ファイル
1632+ setcursor(0,WIDTH_Y-1,COLOR_ERRORTEXT);
1633+ printstr("Input File Name: ");
1634+ setcursorcolor(COLOR_NORMALTEXT);
1635+ //ファイル名入力
1636+ *tempfile=0;
1637+ if(lineinput(tempfile,8+1+3)<0) break; //ESCキー
1638+ if(*tempfile==0) break; //ファイル名入力なし
1639+ }
1640+ else if(f==-1){
1641+ //新規ディレクトリ
1642+ setcursor(0,WIDTH_Y-1,COLOR_ERRORTEXT);
1643+ printstr("Input Dir Name: ");
1644+ setcursorcolor(COLOR_NORMALTEXT);
1645+ //ディレクトリ名入力
1646+ *tempfile=0;
1647+ if(lineinput(tempfile,8+1+3)<0) break; //ESCキー
1648+ if(FSmkdir(tempfile)){
1649+ setcursor(0,WIDTH_Y-1,COLOR_ERRORTEXT);
1650+ printstr("Cannot Make Directory ");
1651+ break;
1652+ }
1653+ }
1654+ else{
1655+ //ファイル名またはディレクトリ名をtempfileにコピー
1656+ ps=filenames[f];
1657+ pd=tempfile;
1658+ while(*ps) *pd++=*ps++;
1659+ *pd=0;
1660+ }
1661+ return f;
1662+ case VK_ESCAPE:
1663+ //ESCキー
1664+ return -3;
1665+ }
1666+ }
1667+}
1668+int getfilelist(int *p_num_dir){
1669+// カレントディレクトリでのディレクトリ、.BAS、.TXT、.INIファイル一覧を読み込む
1670+// *p_num_dir:ディレクトリ数を返す
1671+// filenames[]:ファイル名およびディレクトリ名一覧
1672+// 戻り値 ファイル+ディレクトリ数
1673+
1674+ unsigned char *ps,*pd;
1675+ int filenum;
1676+ SearchRec sr;
1677+ filenum=0;
1678+ //ディレクトリのサーチ
1679+ if(FindFirst("*.*",ATTR_DIRECTORY,&sr)==0){
1680+ do{
1681+ //filenames[]にディレクトリ名の一覧を読み込み
1682+ ps=sr.filename;
1683+ pd=filenames[filenum];
1684+ while(*ps!=0) *pd++=*ps++;
1685+ *pd=0;
1686+ filenum++;
1687+ }
1688+ while(!FindNext(&sr) && filenum<MAXFILENUM);
1689+ }
1690+ *p_num_dir=filenum;
1691+ if(filenum>=MAXFILENUM) return filenum;
1692+ //拡張子 BASファイルのサーチ
1693+ if(FindFirst("*.BAS",ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_ARCHIVE,&sr)==0){
1694+ do{
1695+ //filenames[]にファイル名の一覧を読み込み
1696+ ps=sr.filename;
1697+ pd=filenames[filenum];
1698+ while(*ps!=0) *pd++=*ps++;
1699+ *pd=0;
1700+ filenum++;
1701+ }
1702+ while(!FindNext(&sr) && filenum<MAXFILENUM);
1703+ }
1704+ if(filenum>=MAXFILENUM) return filenum;
1705+ //拡張子 TXTファイルのサーチ
1706+ if(FindFirst("*.TXT",ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_ARCHIVE,&sr)==0){
1707+ do{
1708+ //filenames[]にファイル名の一覧を読み込み
1709+ ps=sr.filename;
1710+ pd=filenames[filenum];
1711+ while(*ps!=0) *pd++=*ps++;
1712+ *pd=0;
1713+ filenum++;
1714+ }
1715+ while(!FindNext(&sr) && filenum<MAXFILENUM);
1716+ }
1717+ if(filenum>=MAXFILENUM) return filenum;
1718+ //拡張子 INIファイルのサーチ
1719+ if(FindFirst("*.INI",ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_ARCHIVE,&sr)==0){
1720+ do{
1721+ //filenames[]にファイル名の一覧を読み込み
1722+ ps=sr.filename;
1723+ pd=filenames[filenum];
1724+ while(*ps!=0) *pd++=*ps++;
1725+ *pd=0;
1726+ filenum++;
1727+ }
1728+ while(!FindNext(&sr) && filenum<MAXFILENUM);
1729+ }
1730+ return filenum;
1731+}
1732+void save_as(int ow){
1733+// 現在のテキストバッファの内容をSDカードに保存
1734+// ow 0:名前を付けて保存  1:上書き保存
1735+// ファイル名はグローバル変数currentfile[]
1736+// ファイル名はキーボードから変更可能
1737+// 成功した場合currentfileを更新
1738+
1739+ int er;
1740+ int filenum,num_dir,f;
1741+ unsigned char *ps,*pd;
1742+
1743+ cls();
1744+ setcursor(0,0,COLOR_NORMALTEXT);
1745+ printstr("Save To SD Card\n");
1746+ if(currentfile[0]==0) ow=0; //ファイル名が設定されていない場合名前を付けて保存
1747+
1748+ //currentfileからtempfileにコピー
1749+ ps=currentfile;
1750+ pd=tempfile;
1751+ while(*ps!=0) *pd++=*ps++;
1752+ *pd=0;
1753+
1754+ //カレントディレクトリを変数cwdpathにコピー
1755+ while(1){
1756+ if(FSgetcwd(cwdpath,PATHNAMEMAX)) break;
1757+ setcursorcolor(COLOR_ERRORTEXT);
1758+ printstr("Cannot Get Current Dir\n");
1759+ if(filesystemretry()) return; //ファイルシステム再初期化、あきらめた場合はreturnする
1760+ }
1761+ //現在のディレクトリのパスを表示
1762+ setcursorcolor(COLOR_NORMALTEXT);
1763+ printstr("Current Directory is\n");
1764+ printstr(cwdpath);
1765+ printchar('\n');
1766+ while(1){
1767+ if(ow==0){
1768+ printstr("Input File Name + [Enter]\n");
1769+ printstr("[ESC] Select File/Dir or Quit\n");
1770+ //ファイル名入力
1771+ if(lineinput(tempfile,8+1+3)<0){
1772+ //ESCキーが押された場合、ファイル選択、ディレクトリ変更画面または終了
1773+ while(1){
1774+ filenum=getfilelist(&num_dir); //ディレクトリ、ファイル名一覧を読み込み
1775+ f=select_dir_file(filenum,num_dir,"Save"); //ファイルの選択
1776+ cls();
1777+ if(f==-3){
1778+ //終了
1779+ FSchdir(cwdpath);//カレントディレクトリを元に戻す
1780+ return;
1781+ }
1782+ else if(f==-2){
1783+ //新規ファイル
1784+ if(overwritecheck(tempfile)==0) break;//上書きチェック
1785+ }
1786+ else if(f<num_dir){
1787+ //新規ディレクトリまたはディレクトリ変更
1788+ FSchdir(tempfile);//ディレクトリ変更して再度ファイル一覧へ
1789+ }
1790+ else break;
1791+ }
1792+ }
1793+ else{
1794+ if(*tempfile==0) continue; //NULL文字列の場合
1795+ if(overwritecheck(tempfile)) continue;
1796+ }
1797+ }
1798+ printstr("Writing...\n");
1799+ er=savetextfile(tempfile); //ファイル保存、er:エラーコード
1800+ if(er==0){
1801+ printstr("OK");
1802+ FSremove(TEMPFILENAME); //実行時に生成する一時ファイルを削除
1803+ //tempfileからcurrentfileにコピーして終了
1804+ ps=tempfile;
1805+ pd=currentfile;
1806+ while(*ps!=0) *pd++=*ps++;
1807+ *pd=0;
1808+ FSgetcwd(cwdpath,PATHNAMEMAX); //カレントパスを更新
1809+ edited=0; //編集済みフラグクリア
1810+ wait60thsec(60);//1秒待ち
1811+ return;
1812+ }
1813+ setcursorcolor(COLOR_ERRORTEXT);
1814+ if(er==ERR_CANTFILEOPEN) printstr("Bad File Name or File Error\n");
1815+ else printstr("Cannot Write\n");
1816+ if(filesystemretry()) return; //ファイルシステム再初期化、あきらめた場合はreturnする
1817+ }
1818+}
1819+
1820+void newtext(void){
1821+// 新規テキスト作成
1822+ unsigned char vk;
1823+ if(edited && num){
1824+ //最終保存後に編集済みの場合、保存の確認
1825+ cls();
1826+ setcursorcolor(COLOR_NORMALTEXT);
1827+ printstr("Save Editing File?\n");
1828+ printstr("Save:[Enter] / Not Save:[ESC]\n");
1829+ while(1){
1830+ inputchar(); //1文字キー入力待ち
1831+ vk=vkey & 0xff;
1832+ if(vk==VK_RETURN || vk==VK_SEPARATOR){
1833+ save_as(0); //名前を付けて保存
1834+ break;
1835+ }
1836+ else if(vk==VK_ESCAPE) break;
1837+ }
1838+ }
1839+ inittextbuf(); //テキストバッファ初期化
1840+ cursor_top(); //カーソルをテキストバッファの先頭に設定
1841+ currentfile[0]=0; //作業中ファイル名クリア
1842+}
1843+
1844+void msra(void){
1845+// Make Self-Running Application (自己実行アプリケーションの作成)
1846+// 最初にソースファイルを名前を付けて保存
1847+// 次にBASICシステムのHEXファイルをソースファイル名の拡張子をHEXにした名前でコピー
1848+
1849+ int er;
1850+ unsigned char *ps,*pd;
1851+ cls();
1852+ setcursor(0,0,COLOR_NORMALTEXT);
1853+ printstr("Make Self-Running Application\n\n");
1854+ printstr("(Work on Root Directory)\n");
1855+
1856+ //カレントディレクトリを変数cwdpathにコピー
1857+ while(1){
1858+ if(FSgetcwd(cwdpath,PATHNAMEMAX)) break;
1859+ setcursorcolor(COLOR_ERRORTEXT);
1860+ printstr("Cannot Get Current Dir\n");
1861+ if(filesystemretry()) return; //ファイルシステム再初期化、あきらめた場合はreturnする
1862+ }
1863+ while(1){
1864+ //カレントディレクトリをルートに変更
1865+ if(FSchdir((char *)ROOTDIR)==0) break;
1866+ setcursorcolor(COLOR_ERRORTEXT);
1867+ printstr("Cannot Change To Root Dir\n");
1868+ if(filesystemretry()) return; //ファイルシステム再初期化、あきらめた場合はreturnする
1869+ }
1870+ //currentfileからtempfileにコピー
1871+ ps=currentfile;
1872+ pd=tempfile;
1873+ while(*ps!=0) *pd++=*ps++;
1874+ *pd=0;
1875+
1876+ while(1){
1877+ setcursorcolor(COLOR_NORMALTEXT);
1878+ printstr("Input File Name (xxx.BAS)\n");
1879+ if(lineinput(tempfile,8+1+3)<0){
1880+ //ESCキーが押された
1881+ FSchdir(cwdpath); //カレントディレクトリを元に戻す
1882+ return;
1883+ }
1884+ ps=tempfile;
1885+ while(*ps!='.' && *ps!=0) ps++;
1886+ if(ps+4>=tempfile+13 ||
1887+ *ps!='.' ||
1888+ (*(ps+1)!='b' && *(ps+1)!='B') ||
1889+ (*(ps+2)!='a' && *(ps+2)!='A') ||
1890+ (*(ps+3)!='s' && *(ps+3)!='S') ||
1891+ *(ps+4)!=0){
1892+ setcursorcolor(COLOR_ERRORTEXT);
1893+ printstr("File Name Must Be xxx.BAS\n");
1894+ continue;
1895+ }
1896+ if(overwritecheck(tempfile)) continue;
1897+ printstr("Writing BASIC File\n");
1898+ er=savetextfile(tempfile); //ファイル保存、er:エラーコード
1899+ if(er==0) break;
1900+ setcursorcolor(COLOR_ERRORTEXT);
1901+ if(er==ERR_CANTFILEOPEN) printstr("Bad File Name or File Error\n");
1902+ else printstr("Cannot Write\n");
1903+
1904+ //ファイルシステム再初期化、あきらめた場合はreturnする
1905+ if(filesystemretry()){
1906+ if(FSchdir(cwdpath)){
1907+ cwdpath[0]='\\';
1908+ cwdpath[1]=0;
1909+ }
1910+ return;
1911+ }
1912+ }
1913+ printstr("OK\n\n");
1914+ FSremove(TEMPFILENAME); //実行時に生成する一時ファイルを削除
1915+ //tempfileからcurrentfileにコピーして終了
1916+ ps=tempfile;
1917+ pd=currentfile;
1918+ while(*ps!=0) *pd++=*ps++;
1919+ *pd=0;
1920+ edited=0; //編集済みフラグクリア
1921+ // 拡張子をHEXにしてBASICシステムファイルをコピー
1922+ *(ps-3)='H';
1923+ *(ps-2)='E';
1924+ *(ps-1)='X';
1925+ if(overwritecheck(tempfile)) return;
1926+ printstr("Copying\n");
1927+ printstr(HEXFILE);
1928+ printstr(" To ");
1929+ printstr(tempfile);
1930+ printstr("\nWait For A While");
1931+ er=sdfilecopy(HEXFILE,tempfile);
1932+ if(FSchdir(cwdpath)){
1933+ cwdpath[0]='\\';
1934+ cwdpath[1]=0;
1935+ }
1936+ if(er==0){
1937+ printstr("\nDone");
1938+ wait60thsec(120);//2秒待ち
1939+ return;
1940+ }
1941+ setcursorcolor(COLOR_ERRORTEXT);
1942+ if(er==ERR_CANTFILEOPEN){
1943+ printstr(HEXFILE);
1944+ printstr(" Not Found\n");
1945+ }
1946+ else if(er==ERR_CANTWRITEFILE){
1947+ printstr("Write Error\n");
1948+ }
1949+ setcursorcolor(COLOR_NORMALTEXT);
1950+ printstr((unsigned char *)Message1);// Hit Any Key
1951+ inputchar(); //1文字入力待ち
1952+ return;
1953+}
1954+int fileload(void){
1955+// SDカードからファイルを選択して読み込み
1956+// currenfile[]にファイル名を記憶
1957+// 対象ファイル拡張子 BASおよびTXT
1958+// 戻り値 0:読み込みを行った -1:読み込みなし
1959+ int filenum,f,er;
1960+ unsigned char *ps,*pd;
1961+ unsigned char vk;
1962+ int num_dir;//ディレクトリ数
1963+
1964+ //ファイルの一覧をSDカードから読み出し
1965+ cls();
1966+ if(edited && num){
1967+ //最終保存後に編集済みの場合、保存の確認
1968+ setcursorcolor(COLOR_NORMALTEXT);
1969+ printstr("Save Program Before Load?\n");
1970+ printstr("Save:[Enter] / Not Save:[ESC]\n");
1971+ while(1){
1972+ inputchar(); //1文字キー入力待ち
1973+ vk=vkey & 0xff;
1974+ if(vk==VK_RETURN || vk==VK_SEPARATOR){
1975+ save_as(0); //名前を付けて保存
1976+ break;
1977+ }
1978+ else if(vk==VK_ESCAPE) break;
1979+ }
1980+ }
1981+ //カレントディレクトリを変数cwdpathにコピー
1982+ while(1){
1983+ if(FSgetcwd(cwdpath,PATHNAMEMAX)) break;
1984+ setcursorcolor(COLOR_ERRORTEXT);
1985+ printstr("Cannot Get Current Dir\n");
1986+ if(filesystemretry()) return -1; //ファイルシステム再初期化、あきらめた場合はreturnする
1987+ }
1988+ while(1){
1989+ filenum=getfilelist(&num_dir); //ディレクトリ、ファイル名一覧を読み込み
1990+ if(filenum==0){
1991+ setcursorcolor(COLOR_ERRORTEXT);
1992+ printstr(".BAS or .TXT File Not Found\n");
1993+ printstr((unsigned char *)Message1);// Hit Any Key
1994+ inputchar(); //1文字入力待ち
1995+ FSchdir(cwdpath);//カレントディレクトリを元に戻す
1996+ return -1;
1997+ }
1998+ //ファイルの選択
1999+ f=select_dir_file(filenum,num_dir,"Load");
2000+ if(f==-3){
2001+ //読み込まずに終了
2002+ FSchdir(cwdpath);//カレントディレクトリを元に戻す
2003+ return -1;
2004+ }
2005+ else if(f==-2){
2006+ //新規ファイルまたはファイル名を入力して読み込み
2007+ er=loadtextfile(tempfile); //テキストバッファにファイル読み込み
2008+ if(er==ERR_CANTFILEOPEN){
2009+ //ファイルが存在しない場合、新規テキスト
2010+ edited=0;
2011+ newtext();
2012+ }
2013+ else if(er==ERR_FILETOOBIG){
2014+ //ファイルサイズエラーの場合、選択画面に戻る
2015+ setcursor(0,WIDTH_Y-1,COLOR_ERRORTEXT);
2016+ printstr("File Too Big ");
2017+ wait60thsec(60);//1秒待ち
2018+ continue;
2019+ }
2020+ //currenfile[]にファイル名をコピー
2021+ ps=tempfile;
2022+ pd=currentfile;
2023+ while(*ps) *pd++=*ps++;
2024+ *pd=0;
2025+ FSgetcwd(cwdpath,PATHNAMEMAX);//cwdpathをカレントディレクトリのパスに変更
2026+ return 0;
2027+ }
2028+ else if(f<num_dir){
2029+ //新規ディレクトリまたはディレクトリ変更して、再度ファイル一覧画面へ
2030+ FSchdir(tempfile);
2031+ }
2032+ else{
2033+ er=loadtextfile(filenames[f]); //テキストバッファにファイル読み込み
2034+ if(er==0){
2035+ //cwdpath[]、currenfile[]にパス、ファイル名をコピーして終了
2036+ FSgetcwd(cwdpath,PATHNAMEMAX);
2037+ ps=filenames[f];
2038+ pd=currentfile;
2039+ while(*ps!=0) *pd++=*ps++;
2040+ *pd=0;
2041+ return 0;
2042+ }
2043+ setcursor(0,WIDTH_Y-1,COLOR_ERRORTEXT);
2044+ if(er==ERR_CANTFILEOPEN) printstr("Cannot Open File ");
2045+ else if(er=ERR_FILETOOBIG) printstr("File Too Big ");
2046+ wait60thsec(60);//1秒待ち
2047+ }
2048+ }
2049+}
2050+void changewidth(void){
2051+// 30文字モードと40文字モードの切り替え
2052+ if(twidth==WIDTH_X1) set_width(1);
2053+ else set_width(0);
2054+ cursor_top(); //カーソルをテキストバッファの先頭に設定
2055+ redraw(); //再描画
2056+}
2057+void run(int test){
2058+//KM-BASICコンパイル&実行
2059+// test 0:コンパイルと実行、0以外:コンパイルのみで終了
2060+ int er,er2;
2061+ FSFILE *fp;
2062+ unsigned int disptoppos,cursorpos;
2063+ unsigned char widthmode;
2064+ int i,edited1;
2065+ _tbuf *bp;
2066+ unsigned short ix;
2067+ unsigned char *p;
2068+
2069+ cls();
2070+ setcursor(0,0,COLOR_NORMALTEXT);
2071+ while(1){
2072+ //カレントディレクトリをルートに変更
2073+ if(FSchdir((char *)ROOTDIR)){
2074+ setcursorcolor(COLOR_ERRORTEXT);
2075+ printstr("Cannot Change To Root Dir\n");
2076+ if(filesystemretry()) return; //ファイルシステム再初期化、あきらめた場合はreturnする
2077+ continue;
2078+ }
2079+ //ルートディレクトリのパス名保存ファイルに実行時パスを保存
2080+ fp=FSfopen(WORKDIRFILE,"w");
2081+ if(fp==NULL){
2082+ setcursorcolor(COLOR_ERRORTEXT);
2083+ printstr("Cannot Open Work Dir File\n");
2084+ if(filesystemretry()){
2085+ //ファイルシステム再初期化、あきらめた場合はカレントディレクトリを戻しreturnする
2086+ FSchdir(cwdpath);
2087+ return;
2088+ }
2089+ continue;
2090+ }
2091+ for(p=cwdpath;*p;p++) ;
2092+ er=FSfwrite(cwdpath,1,p-cwdpath+1,fp);
2093+ FSfclose(fp);
2094+ if(er!=p-cwdpath+1){
2095+ FSremove(WORKDIRFILE);
2096+ setcursorcolor(COLOR_ERRORTEXT);
2097+ printstr("Cannot Write Work Dir File\n");
2098+ if(filesystemretry()){
2099+ //ファイルシステム再初期化、あきらめた場合はカレントディレクトリを戻しreturnする
2100+ FSchdir(cwdpath);
2101+ return;
2102+ }
2103+ continue;
2104+ }
2105+ break;
2106+ }
2107+ while(1){
2108+ //カレントディレクトリを元に戻す
2109+ if(FSchdir(cwdpath)){
2110+ setcursorcolor(COLOR_ERRORTEXT);
2111+ printstr("Cannot Change To CWD\n");
2112+ if(filesystemretry()) return; //ファイルシステム再初期化、あきらめた場合はreturnする
2113+ continue;
2114+ }
2115+ //実行用引渡しファイルに保存
2116+ if(savetextfile(TEMPFILENAME)){
2117+ setcursorcolor(COLOR_ERRORTEXT);
2118+ printstr("Cannot Write To SD Card\n");
2119+ if(filesystemretry()) return; //ファイルシステム再初期化、あきらめた場合はreturnする
2120+ continue;
2121+ }
2122+ break;
2123+ }
2124+
2125+ //カーソル位置、画面表示位置、画面モードの保存
2126+ disptoppos=bpixtopos(disptopbp,disptopix);
2127+ cursorpos=bpixtopos(cursorbp,cursorix);
2128+ widthmode=twidth;
2129+ edited1=edited; //編集済みフラグの一時退避
2130+ set_width(0);//30文字モードに設定
2131+
2132+ // Enable Break key
2133+ g_disable_break=0;
2134+ //KM-BASIC実行
2135+ er2=runbasic(TEMPFILENAME,test);
2136+
2137+ stopPCG();//システムフォントに戻す
2138+ setcursorcolor(COLOR_NORMALTEXT);
2139+ printchar('\n');
2140+ printstr((unsigned char *)Message1);// Hit Any Key
2141+ do ps2readkey(); //キーバッファが空になるまで読み出し
2142+ while(vkey!=0);
2143+ ps2mode(); //キーボード有効化
2144+ inputchar(); //1文字入力待ち
2145+ stop_music(); //音楽再生停止
2146+ init_composite(); //パレット初期化のため画面初期化
2147+ //画面モードを戻す
2148+ if(widthmode==WIDTH_X1) set_width(0);
2149+ else set_width(1);
2150+
2151+ FSgetcwd(cwdpath,PATHNAMEMAX);//カレントディレクトリパス変数を戻す
2152+ while(1){
2153+ //カレントディレクトリをルートに変更
2154+ if(FSchdir((char *)ROOTDIR)){
2155+ setcursorcolor(COLOR_ERRORTEXT);
2156+ printstr("Cannot Change To Root Dir\n");
2157+ filesystemretry(); //ファイルシステム再初期化
2158+ continue;
2159+ }
2160+ //ルートディレクトリのパス名保存ファイルからパス名を読み出し
2161+ fp=FSfopen(WORKDIRFILE,"r");
2162+ if(fp==NULL){
2163+ setcursorcolor(COLOR_ERRORTEXT);
2164+ printstr("Cannot Open Work Dir File\n");
2165+ filesystemretry(); //ファイルシステム再初期化
2166+ continue;
2167+ }
2168+ er=FSfread(cwdpath,1,PATHNAMEMAX,fp);
2169+ FSfclose(fp);
2170+ if(er<=0){
2171+ setcursorcolor(COLOR_ERRORTEXT);
2172+ printstr("Cannot Read Work Dir File\n");
2173+ filesystemretry(); //ファイルシステム再初期化
2174+ continue;
2175+ }
2176+ FSremove(WORKDIRFILE); //パス名保存ファイル削除
2177+ break;
2178+ }
2179+ while(1){
2180+ //カレントディレクトリを元に戻す
2181+ if(FSchdir(cwdpath)){
2182+ setcursorcolor(COLOR_ERRORTEXT);
2183+ printstr("Cannot Change To CWD\n");
2184+ filesystemretry(); //ファイルシステム再初期化
2185+ continue;
2186+ }
2187+ //実行用引渡しファイルから元に戻す
2188+ if(loadtextfile(TEMPFILENAME)){
2189+ setcursorcolor(COLOR_ERRORTEXT);
2190+ printstr("Cannot Load From SD Card\n");
2191+ filesystemretry(); //ファイルシステム再初期化
2192+ continue;
2193+ }
2194+ break;
2195+ }
2196+ if(er2<=0){
2197+ //正常終了またはファイルエラーまたはリンクエラーの場合
2198+ //カーソルを元の位置に設定
2199+ disptopbp=postobpix(disptoppos,&disptopix);
2200+ cursorbp=postobpix(cursorpos,&cursorix);
2201+ }
2202+ else{
2203+ //コンパイルエラーの場合
2204+ //カーソルをエラー行で画面トップに移動
2205+ disptopbp=linetobpix(er2,&disptopix);
2206+ cursorbp=disptopbp;
2207+ cursorix=disptopix;
2208+ cx=0;
2209+ cx2=0;
2210+ cy=0;
2211+ line_no=er2;
2212+ //中央になるようスクロール
2213+ for(i=0;i<EDITWIDTHY/2;i++){
2214+ //画面行数半分カーソルを上に移動
2215+ bp=disptopbp;
2216+ ix=disptopix;
2217+ cursor_up();
2218+ if(bp==disptopbp && ix==disptopix) break; //最上行で移動できなかった場合抜ける
2219+ }
2220+ for(;i>0;i--) cursor_down(); //元のY座標までカーソルを下に移動
2221+ }
2222+ cursorbp1=NULL; //範囲選択モード解除
2223+ clipsize=0; //クリップボードクリア
2224+ edited=edited1;
2225+ FSremove(TEMPFILENAME);
2226+}
2227+void displaybottomline(void){
2228+//エディター画面最下行の表示
2229+ unsigned char *p;
2230+ unsigned char c;
2231+ int t;
2232+ p=cursor; //カーソル位置の退避
2233+ c=cursorcolor;
2234+ setcursor(0,WIDTH_Y-1,COLOR_BOTTOMLINE);
2235+ if(shiftkeys() & CHK_SHIFT){
2236+ printstr("NEW |MSRA|WDTH|TEST|");
2237+ setcursorcolor(COLOR_ERRORTEXT);
2238+ t=TBUFMAXSIZE-num;
2239+ if(t==0) t=1;
2240+ while(t<10000){
2241+ printchar(' ');
2242+ t*=10;
2243+ }
2244+ printstr("LEFT:");
2245+ printnum(TBUFMAXSIZE-num);
2246+ }
2247+ else{
2248+ printstr("LOAD|SAVE| |RUN |");
2249+ setcursorcolor(COLOR_ERRORTEXT);
2250+ t=line_no;
2251+ if(t==0) t=1;
2252+ while(t<10000){
2253+ printchar(' ');
2254+ t*=10;
2255+ }
2256+ printstr("LINE:");
2257+ printnum(line_no);
2258+ }
2259+ cursor=p; //カーソル位置戻し
2260+ cursorcolor=c;
2261+}
2262+void normal_code_process(unsigned char k){
2263+// 通常文字入力処理
2264+// k:入力された文字コード
2265+ int i;
2266+
2267+ edited=1; //編集済みフラグ
2268+ if(insertmode || k=='\n' || cursorbp1!=NULL){ //挿入モード
2269+ if(cursorbp1!=NULL) deletearea();//選択範囲を削除
2270+ i=insertchar(cursorbp,cursorix,k,0);//テキストバッファに1文字挿入
2271+ if(i>0){
2272+ //バッファ空きがあるのに挿入失敗の場合
2273+ gabagecollect2(); //全体ガベージコレクション
2274+ i=insertchar(cursorbp,cursorix,k,0);//テキストバッファに1文字挿入
2275+ }
2276+ if(i==0) cursor_right();//画面上、バッファ上のカーソル位置を1つ後ろに移動
2277+ }
2278+ else{ //上書きモード
2279+ i=overwritechar(cursorbp,cursorix,k,0);//テキストバッファに1文字上書き
2280+ if(i>0){
2281+ //バッファ空きがあるのに上書き(挿入)失敗の場合
2282+ //(行末やバッファ最後尾では挿入)
2283+ gabagecollect2(); //全体ガベージコレクション
2284+ i=overwritechar(cursorbp,cursorix,k,0);//テキストバッファに1文字上書き
2285+ }
2286+ if(i==0) cursor_right();//画面上、バッファ上のカーソル位置を1つ後ろに移動
2287+ }
2288+}
2289+void control_code_process(unsigned char k,unsigned char sh){
2290+// 制御文字入力処理
2291+// k:制御文字の仮想キーコード
2292+// sh:シフト関連キー状態
2293+
2294+ save_cursor(); //カーソル関連変数退避(カーソル移動できなかった場合戻すため)
2295+ switch(k){
2296+ case VK_LEFT:
2297+ case VK_NUMPAD4:
2298+ //シフトキー押下していなければ範囲選択モード解除(NumLock+シフト+テンキーでも解除)
2299+ if((sh & CHK_SHIFT)==0 || (k==VK_NUMPAD4) && (sh & CHK_NUMLK)) cursorbp1=NULL;
2300+ else if(cursorbp1==NULL) set_areamode(); //範囲選択モードでなければ範囲選択モード開始
2301+ if(sh & CHK_CTRL){
2302+ //CTRL+左矢印でHome
2303+ cursor_home();
2304+ break;
2305+ }
2306+ cursor_left();
2307+ if(cursorbp1!=NULL && (disptopbp!=disptopbp_t || disptopix!=disptopix_t)){
2308+ //範囲選択モードで画面スクロールがあった場合
2309+ if(cy1<EDITWIDTHY-1) cy1++; //範囲スタート位置もスクロール
2310+ else restore_cursor(); //カーソル位置を戻す(画面範囲外の範囲選択禁止)
2311+ }
2312+ break;
2313+ case VK_RIGHT:
2314+ case VK_NUMPAD6:
2315+ //シフトキー押下していなければ範囲選択モード解除(NumLock+シフト+テンキーでも解除)
2316+ if((sh & CHK_SHIFT)==0 || (k==VK_NUMPAD6) && (sh & CHK_NUMLK)) cursorbp1=NULL;
2317+ else if(cursorbp1==NULL) set_areamode(); //範囲選択モードでなければ範囲選択モード開始
2318+ if(sh & CHK_CTRL){
2319+ //CTRL+右矢印でEnd
2320+ cursor_end();
2321+ break;
2322+ }
2323+ cursor_right();
2324+ if(cursorbp1!=NULL && (disptopbp!=disptopbp_t || disptopix!=disptopix_t)){
2325+ //範囲選択モードで画面スクロールがあった場合
2326+ if(cy1>0) cy1--; //範囲スタート位置もスクロール
2327+ else restore_cursor(); //カーソル位置を戻す(画面範囲外の範囲選択禁止)
2328+ }
2329+ break;
2330+ case VK_UP:
2331+ case VK_NUMPAD8:
2332+ //シフトキー押下していなければ範囲選択モード解除(NumLock+シフト+テンキーでも解除)
2333+ if((sh & CHK_SHIFT)==0 || (k==VK_NUMPAD8) && (sh & CHK_NUMLK)) cursorbp1=NULL;
2334+ else if(cursorbp1==NULL) set_areamode(); //範囲選択モードでなければ範囲選択モード開始
2335+ cursor_up();
2336+ if(cursorbp1!=NULL && (disptopbp!=disptopbp_t || disptopix!=disptopix_t)){
2337+ //範囲選択モードで画面スクロールがあった場合
2338+ if(cy1<EDITWIDTHY-1) cy1++; //範囲スタート位置もスクロール
2339+ else restore_cursor(); //カーソル位置を戻す(画面範囲外の範囲選択禁止)
2340+ }
2341+ break;
2342+ case VK_DOWN:
2343+ case VK_NUMPAD2:
2344+ //シフトキー押下していなければ範囲選択モード解除(NumLock+シフト+テンキーでも解除)
2345+ if((sh & CHK_SHIFT)==0 || (k==VK_NUMPAD2) && (sh & CHK_NUMLK)) cursorbp1=NULL;
2346+ else if(cursorbp1==NULL) set_areamode(); //範囲選択モードでなければ範囲選択モード開始
2347+ cursor_down();
2348+ if(cursorbp1!=NULL && (disptopbp!=disptopbp_t || disptopix!=disptopix_t)){
2349+ //範囲選択モードで画面スクロールがあった場合
2350+ if(cy1>0) cy1--; //範囲スタート位置もスクロール
2351+ else restore_cursor(); //カーソル位置を戻す(画面範囲外の範囲選択禁止)
2352+ }
2353+ break;
2354+ case VK_HOME:
2355+ case VK_NUMPAD7:
2356+ //シフトキー押下していなければ範囲選択モード解除(NumLock+シフト+テンキーでも解除)
2357+ if((sh & CHK_SHIFT)==0 || (k==VK_NUMPAD7) && (sh & CHK_NUMLK)) cursorbp1=NULL;
2358+ else if(cursorbp1==NULL) set_areamode(); //範囲選択モードでなければ範囲選択モード開始
2359+ cursor_home();
2360+ break;
2361+ case VK_END:
2362+ case VK_NUMPAD1:
2363+ //シフトキー押下していなければ範囲選択モード解除(NumLock+シフト+テンキーでも解除)
2364+ if((sh & CHK_SHIFT)==0 || (k==VK_NUMPAD1) && (sh & CHK_NUMLK)) cursorbp1=NULL;
2365+ else if(cursorbp1==NULL) set_areamode(); //範囲選択モードでなければ範囲選択モード開始
2366+ cursor_end();
2367+ break;
2368+ case VK_PRIOR: // PageUpキー
2369+ case VK_NUMPAD9:
2370+ //シフト+PageUpは無効(NumLock+シフト+「9」除く)
2371+ if((sh & CHK_SHIFT) && ((k!=VK_NUMPAD9) || ((sh & CHK_NUMLK)==0))) break;
2372+ cursorbp1=NULL; //範囲選択モード解除
2373+ cursor_pageup();
2374+ break;
2375+ case VK_NEXT: // PageDownキー
2376+ case VK_NUMPAD3:
2377+ //シフト+PageDownは無効(NumLock+シフト+「3」除く)
2378+ if((sh & CHK_SHIFT) && ((k!=VK_NUMPAD3) || ((sh & CHK_NUMLK)==0))) break;
2379+ cursorbp1=NULL; //範囲選択モード解除
2380+ cursor_pagedown();
2381+ break;
2382+ case VK_DELETE: //Deleteキー
2383+ case VK_DECIMAL: //テンキーの「.」
2384+ edited=1; //編集済みフラグ
2385+ if(cursorbp1!=NULL) deletearea();//選択範囲を削除
2386+ else deletechar(cursorbp,cursorix,0);
2387+ break;
2388+ case VK_BACK: //BackSpaceキー
2389+ edited=1; //編集済みフラグ
2390+ if(cursorbp1!=NULL){
2391+ deletearea();//選択範囲を削除
2392+ break;
2393+ }
2394+ if(cursorix==0 && cursorbp->prev==NULL) break; //バッファ先頭では無視
2395+ cursor_left();
2396+ deletechar(cursorbp,cursorix,-1);
2397+ break;
2398+ case VK_INSERT:
2399+ case VK_NUMPAD0:
2400+ insertmode^=1; //挿入モード、上書きモードを切り替え
2401+ break;
2402+ case 'C':
2403+ //CTRL+C、クリップボードにコピー
2404+ if(cursorbp1!=NULL && (sh & CHK_CTRL)) clipcopy();
2405+ break;
2406+ case 'X':
2407+ //CTRL+X、クリップボードに切り取り
2408+ if(cursorbp1!=NULL && (sh & CHK_CTRL)){
2409+ clipcopy();
2410+ deletearea(); //選択範囲の削除
2411+ edited=1; //編集済みフラグ
2412+ }
2413+ break;
2414+ case 'V':
2415+ //CTRL+V、クリップボードから貼り付け
2416+ if((sh & CHK_CTRL)==0) break;
2417+ if(clipsize==0) break;
2418+ edited=1; //編集済みフラグ
2419+ if(cursorbp1!=NULL){
2420+ //範囲選択している時は削除してから貼り付け
2421+ if(num-countarea()+clipsize<=TBUFMAXSIZE){ //バッファ空き容量チェック
2422+ deletearea();//選択範囲を削除
2423+ clippaste();//クリップボード貼り付け
2424+ }
2425+ }
2426+ else{
2427+ if(num+clipsize<=TBUFMAXSIZE){ //バッファ空き容量チェック
2428+ clippaste();//クリップボード貼り付け
2429+ }
2430+ }
2431+ break;
2432+ case 'S':
2433+ //CTRL+S、SDカードに保存
2434+ if(num==0) break;
2435+ if(sh & CHK_CTRL) save_as(1); //上書き保存
2436+ break;
2437+ case 'O':
2438+ //CTRL+O、ファイル読み込み
2439+ if(sh & CHK_CTRL){
2440+ if(fileload()==0){ //ファイルを選択して読み込み
2441+ //読み込みを行った場合、カーソル位置を先頭に
2442+ cursor_top();
2443+ }
2444+ }
2445+ break;
2446+ case 'N':
2447+ //CTRL+N、新規作成
2448+ if(sh & CHK_CTRL) newtext();
2449+ break;
2450+ case VK_F1: //F1キー
2451+ if(sh & CHK_SHIFT) newtext();//SHIFT+F1キー 新規作成
2452+ else{
2453+ //ファイル読み込み
2454+ if(fileload()==0){ //ファイルを選択して読み込み
2455+ //読み込みを行った場合、カーソル位置を先頭に
2456+ cursor_top();
2457+ }
2458+ }
2459+ break;
2460+ case VK_F2: //F2キー
2461+ if(num==0) break;
2462+ if(sh & CHK_SHIFT) msra(); //create direct running file
2463+ else save_as(0); //ファイル名を付けて保存
2464+ break;
2465+ case VK_F3: //F3キー
2466+ if(sh & CHK_SHIFT) changewidth(); //30文字モード、40文字モード切り替え
2467+ break;
2468+ case VK_F4: //F4キー
2469+ if(num==0) break;
2470+ if(sh & CHK_SHIFT) run(1); //コンパイルテスト
2471+ else run(0); //コンパイル&実行
2472+ break;
2473+ case 'Z':
2474+ //CTRL+Z、アンドゥ
2475+ if(sh & CHK_CTRL) undoexec();
2476+ break;
2477+ }
2478+}
2479+void texteditor(void){
2480+//テキストエディター本体
2481+ unsigned char k1,k2,sh;
2482+ FSFILE *fp;
2483+
2484+ editormallocp=RAM;
2485+ TextBuffer=(_tbuf *)editormalloc(sizeof(_tbuf)*TBUFMAXLINE);
2486+ clipboard=editormalloc(WIDTH_X2*EDITWIDTHY);
2487+ filebuf=editormalloc(FILEBUFSIZE);
2488+ cwdpath=editormalloc(PATHNAMEMAX);
2489+ filenames=(unsigned char (*)[])editormalloc(MAXFILENUM*13);
2490+ undobuf=editormalloc(UNDOBUFSIZE);
2491+
2492+// TextBuffer=(_tbuf *)RAM;
2493+// clipboard=(unsigned char *)TextBuffer+sizeof(_tbuf)*TBUFMAXLINE;
2494+// filebuf=clipboard+WIDTH_X2*EDITWIDTHY;
2495+// cwdpath=filebuf+FILEBUFSIZE;
2496+// filenames=(unsigned char (*)[])(cwdpath+PATHNAMEMAX);
2497+// undobuf=(unsigned char *)filenames+MAXFILENUM*13;
2498+
2499+ inittextbuf(); //テキストバッファ初期化
2500+ currentfile[0]=0; //作業中ファイル名クリア
2501+ cwdpath[0]='\\'; //カレントディレクトリをルートに設定
2502+ cwdpath[1]=0;
2503+
2504+ //実行時生成一時ファイルがあった場合は読み込む
2505+ fp=FSfopen(WORKDIRFILE,"r");
2506+ if(fp!=NULL){
2507+ FSfread(cwdpath,1,PATHNAMEMAX,fp);
2508+ FSfclose(fp);
2509+ FSchdir(cwdpath);
2510+ if(loadtextfile(TEMPFILENAME)==0){
2511+ edited=1;
2512+ setcursorcolor(COLOR_ERRORTEXT);
2513+ printstr("Temporary File Loaded\n");
2514+ printstr("Current Directory is\n");
2515+ setcursorcolor(COLOR_DIR);
2516+ printstr(cwdpath);
2517+ setcursorcolor(COLOR_ERRORTEXT);
2518+ printstr("\nSave To SD Card If Necessary\n");
2519+ setcursorcolor(COLOR_NORMALTEXT);
2520+ printstr((unsigned char *)Message1); //Hit Any Key
2521+ inputchar(); //1文字入力待ち
2522+ }
2523+ else{
2524+ cwdpath[0]='\\'; //カレントディレクトリをルートに設定
2525+ cwdpath[1]=0;
2526+ }
2527+ }
2528+ cursor_top(); //カーソルをテキストバッファの先頭に移動
2529+ insertmode=1; //0:上書き、1:挿入
2530+ clipsize=0; //クリップボードクリア
2531+ blinktimer=0; //カーソル点滅タイマークリア
2532+
2533+ while(1){
2534+ redraw();//画面再描画
2535+ setcursor(cx,cy,COLOR_NORMALTEXT);
2536+ getcursorchar(); //カーソル位置の文字を退避(カーソル点滅用)
2537+ while(1){
2538+ //キー入力待ちループ
2539+ wait60thsec(1); //60分の1秒ウェイト
2540+ blinkcursorchar(); //カーソル点滅させる
2541+ k1=ps2readkey(); //キーバッファから読み込み、k1:通常文字入力の場合ASCIIコード
2542+ displaybottomline(); //画面最下行にファンクションキー機能表示
2543+ if(vkey) break; //キーが押された場合ループから抜ける
2544+ if(cursorbp1==NULL) gabagecollect1(); //1バイトガベージコレクション(範囲選択時はしない)
2545+ }
2546+ resetcursorchar(); //カーソルを元の文字表示に戻す
2547+ k2=(unsigned char)vkey; //k2:仮想キーコード
2548+ sh=vkey>>8; //sh:シフト関連キー状態
2549+ if(k2==VK_RETURN || k2==VK_SEPARATOR) k1='\n'; //Enter押下は単純に改行文字を入力とする
2550+ if(k1) normal_code_process(k1); //通常文字が入力された場合
2551+ else control_code_process(k2,sh); //制御文字が入力された場合
2552+ if(cursorbp1!=NULL && cx==cx1 && cy==cy1) cursorbp1=NULL;//選択範囲の開始と終了が重なったら範囲選択モード解除
2553+ }
2554+}
--- mips/branches/zoeaobjective/envspecific.c (nonexistent)
+++ mips/branches/zoeaobjective/envspecific.c (revision 271)
@@ -0,0 +1,249 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by Katsumi.
4+ http://hp.vector.co.jp/authors/VA016157/
5+ kmorimatsu@users.sourceforge.jp
6+*/
7+
8+#include <xc.h>
9+#include "main.h"
10+#include "compiler.h"
11+#include "videoout.h"
12+#include "ps2keyboard.h"
13+
14+/*
15+ int readbuttons();
16+ Read the tact switches.
17+ For Zoea, disable PS/2 keyboard and enable tact switches, then read.
18+*/
19+
20+void pre_run(){
21+ // Currently, do nothing.
22+}
23+
24+void post_run(){
25+ // Cool down
26+ set_graphmode(0);
27+ g_use_graphic=0;
28+}
29+
30+int readbuttons(){
31+ // Enable tact switches
32+ if (inPS2MODE()) {
33+ buttonmode();
34+ }
35+ return KEYPORT;
36+}
37+
38+void scroll30(int x,int y){
39+ int i,j;
40+ int vector=y*WIDTH_X1+x;
41+ if (vector<0) {
42+ // Copy data from upper address to lower address
43+ for(i=0-vector;i<WIDTH_X1*WIDTH_Y;i++){
44+ TVRAM[i+vector]=TVRAM[i];
45+ TVRAM[WIDTH_X1*WIDTH_Y+i+vector]=TVRAM[WIDTH_X1*WIDTH_Y+i];
46+ }
47+ } else if (0<vector) {
48+ // Copy data from lower address to upper address
49+ for(i=WIDTH_X1*WIDTH_Y-vector-1;0<=i;i--){
50+ TVRAM[i+vector]=TVRAM[i];
51+ TVRAM[WIDTH_X1*WIDTH_Y+i+vector]=TVRAM[WIDTH_X1*WIDTH_Y+i];
52+ }
53+ } else {
54+ return;
55+ }
56+ if (x<0) {
57+ // Fill blanc at right
58+ for(i=x;i<0;i++){
59+ for(j=WIDTH_X1+i;j<WIDTH_X1*WIDTH_Y;j+=WIDTH_X1){
60+ TVRAM[j]=0x00;
61+ TVRAM[WIDTH_X1*WIDTH_Y+j]=cursorcolor;
62+ }
63+ }
64+ } else if (0<x) {
65+ // Fill blanc at left
66+ for(i=0;i<x;i++){
67+ for(j=i;j<WIDTH_X1*WIDTH_Y;j+=WIDTH_X1){
68+ TVRAM[j]=0x00;
69+ TVRAM[WIDTH_X1*WIDTH_Y+j]=cursorcolor;
70+ }
71+ }
72+ }
73+ if (y<0) {
74+ // Fill blanc at bottom
75+ for(i=WIDTH_X1*(WIDTH_Y+y);i<WIDTH_X1*WIDTH_Y;i++){
76+ TVRAM[i]=0x00;
77+ TVRAM[WIDTH_X1*WIDTH_Y+i]=cursorcolor;
78+ }
79+ } else if (0<y) {
80+ // Fill blanc at top
81+ for(i=0;i<WIDTH_X1*y;i++){
82+ TVRAM[i]=0x00;
83+ TVRAM[WIDTH_X1*WIDTH_Y+i]=cursorcolor;
84+ }
85+ }
86+}
87+
88+void scroll40(int x,int y){
89+ int i,j;
90+ int vector=y*WIDTH_X2+x;
91+ if (vector<0) {
92+ // Copy data from upper address to lower address
93+ for(i=0-vector;i<WIDTH_X2*WIDTH_Y;i++){
94+ TVRAM[i+vector]=TVRAM[i];
95+ TVRAM[WIDTH_X2*WIDTH_Y+i+vector]=TVRAM[WIDTH_X2*WIDTH_Y+i];
96+ }
97+ } else if (0<vector) {
98+ // Copy data from lower address to upper address
99+ for(i=WIDTH_X2*WIDTH_Y-vector-1;0<=i;i--){
100+ TVRAM[i+vector]=TVRAM[i];
101+ TVRAM[WIDTH_X2*WIDTH_Y+i+vector]=TVRAM[WIDTH_X2*WIDTH_Y+i];
102+ }
103+ } else {
104+ return;
105+ }
106+ if (x<0) {
107+ // Fill blanc at right
108+ for(i=x;i<0;i++){
109+ for(j=WIDTH_X2+i;j<WIDTH_X2*WIDTH_Y;j+=WIDTH_X2){
110+ TVRAM[j]=0x00;
111+ TVRAM[WIDTH_X2*WIDTH_Y+j]=cursorcolor;
112+ }
113+ }
114+ } else if (0<x) {
115+ // Fill blanc at left
116+ for(i=0;i<x;i++){
117+ for(j=i;j<WIDTH_X2*WIDTH_Y;j+=WIDTH_X2){
118+ TVRAM[j]=0x00;
119+ TVRAM[WIDTH_X2*WIDTH_Y+j]=cursorcolor;
120+ }
121+ }
122+ }
123+ if (y<0) {
124+ // Fill blanc at bottom
125+ for(i=WIDTH_X2*(WIDTH_Y+y);i<WIDTH_X2*WIDTH_Y;i++){
126+ TVRAM[i]=0x00;
127+ TVRAM[WIDTH_X2*WIDTH_Y+i]=cursorcolor;
128+ }
129+ } else if (0<y) {
130+ // Fill blanc at top
131+ for(i=0;i<WIDTH_X2*y;i++){
132+ TVRAM[i]=0x00;
133+ TVRAM[WIDTH_X2*WIDTH_Y+i]=cursorcolor;
134+ }
135+ }
136+}
137+
138+/*
139+ void scroll(int x, int y);
140+ Scroll
141+*/
142+
143+void scroll(int x, int y){
144+ if (twidth==40) scroll40(x,y);
145+ else scroll30(x,y);
146+}
147+
148+void allocate_graphic_area(){
149+ if (!g_graphic_area) {
150+ // Use this pointer like unsigned short GVRAM[G_H_WORD*G_Y_RES] __attribute__ ((aligned (4)));
151+ g_graphic_area=alloc_memory(G_H_WORD*G_Y_RES/2,ALLOC_GRAPHIC_BLOCK);
152+ // Start graphic and clear screen
153+ init_graphic(g_graphic_area);
154+ }
155+}
156+
157+void usegraphic(int mode){
158+ // Modes; 0: stop GRAPHIC, 1: use GRAPHIC, 2: reset GRAPHIC and use it
159+ switch(mode){
160+ case 0:
161+ if (g_use_graphic){
162+ // Stop music before changing CPU speed
163+ stop_music();
164+ // Stop GRAPHIC if used
165+ set_graphmode(0);
166+ g_use_graphic=0;
167+ } else {
168+ // Prepare GRAPHIC area if not used and not allcated.
169+ allocate_graphic_area();
170+ }
171+ break;
172+ case 2:
173+ // Reset GRAPHIC and use it
174+ g_graphic_area=0;
175+ // Continue to case 1:
176+ case 1:
177+ case 3:
178+ default:
179+ // Use GRAPHIC
180+ allocate_graphic_area();
181+ // Start showing GRAPHIC with mode 1, but not with mode 3
182+ if (mode !=3 && !g_use_graphic){
183+ // Stop music before changing CPU speed
184+ stop_music();
185+ // Change to graphic mode.
186+ set_graphmode(1);
187+ g_use_graphic=1;
188+ }
189+ break;
190+ }
191+}
192+
193+void videowidth(int width){
194+ switch(width){
195+ case 30:
196+ if (twidth!=30) set_width(0);
197+ break;
198+ case 40:
199+ if (twidth!=40) set_width(1);
200+ break;
201+ default:
202+ break;
203+ }
204+}
205+
206+int lib_system(int a0, int a1 ,int v0, int a3, int g_gcolor, int g_prev_x, int g_prev_y){
207+ switch(a0){
208+ // Version info
209+ case 0: return (int)SYSVER1;
210+ case 1: return (int)SYSVER2;
211+ case 2: return (int)BASVER;
212+ case 3: return (int)FILENAME_FLASH_ADDRESS;
213+ // Display info
214+ case 20: return twidth;
215+ case 21: return WIDTH_Y;
216+ case 22: return G_X_RES;
217+ case 23: return G_Y_RES;
218+ case 24: return cursorcolor;
219+ case 25: return g_gcolor;
220+ case 26: return ((int)(cursor-TVRAM))%twidth;
221+ case 27: return ((int)(cursor-TVRAM))/twidth;
222+ case 28: return g_prev_x;
223+ case 29: return g_prev_y;
224+ // Keyboard info
225+ case 40: return (int)inPS2MODE();
226+ case 41: return (int)vkey;
227+ case 42: return (int)lockkey;
228+ case 43: return (int)keytype;
229+ // Pointers to gloval variables
230+ case 100: return (int)&g_var_mem[0];
231+ case 101: return (int)&g_rnd_seed;
232+ case 102: return (int)&TVRAM[0];
233+ case 103: return (int)&FontData[0];
234+ case 104: return (int)g_var_mem[ALLOC_PCG_BLOCK];
235+ case 105: return (int)g_var_mem[ALLOC_GRAPHIC_BLOCK];
236+ // Change system settings
237+ case 200:
238+ // ON/OFF monitor
239+ if (v0) {
240+ start_composite();
241+ } else {
242+ stop_composite();
243+ }
244+ break;
245+ default:
246+ break;
247+ }
248+ return 0;
249+}
--- mips/branches/zoeaobjective/compiler.h (nonexistent)
+++ mips/branches/zoeaobjective/compiler.h (revision 271)
@@ -0,0 +1,376 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by Katsumi.
4+ http://hp.vector.co.jp/authors/VA016157/
5+ kmorimatsu@users.sourceforge.jp
6+*/
7+
8+// Include envilonment specific configurations
9+#include "envspecific.h"
10+
11+/* Definitions */
12+// Number of variables (including temporary ones)
13+#define ALLOC_VAR_NUM 36
14+// Block # dedicated for PCG
15+#define ALLOC_PCG_BLOCK 36
16+// Block # dedicated for GRAPHIC
17+#define ALLOC_GRAPHIC_BLOCK 37
18+// Block # dedicated for PLAYWAVE
19+#define ALLOC_WAVE_BLOCK 38
20+// Start # for long name variables
21+#define ALLOC_LNV_BLOCK 39
22+// Number of long name variables
23+#define ALLOC_LNV_NUM 190
24+// Start # of permanent blocks
25+#define ALLOC_PERM_BLOCK 229
26+// Number of blocks that can be assigned for memory allocation (including all above)
27+#define ALLOC_BLOCK_NUM 239
28+
29+// Persistent RAM bytes used for object, heap and exception data
30+#ifndef PERSISTENT_RAM_SIZE
31+ // This must be defined in envspecific.h
32+ #define PERSISTENT_RAM_SIZE (1024*53)
33+#endif
34+// Exception data area bytes
35+#define EXCEPTION_DATA_SIZE (64)
36+// RAM size used for object and heap
37+#define RAMSIZE (PERSISTENT_RAM_SIZE-EXCEPTION_DATA_SIZE)
38+
39+/* Enums */
40+enum variable{
41+ VAR_INTEGER,
42+ VAR_FLOAT,
43+ VAR_STRING
44+};
45+
46+#define OP_MASK 0x001F
47+enum operator{
48+ OP_VOID=0,
49+ OP_OR =1,
50+ OP_AND =2,
51+ OP_XOR =3,
52+ OP_EQ =4,
53+ OP_NEQ =5,
54+ OP_LT =6,
55+ OP_LTE =7,
56+ OP_MT =8,
57+ OP_MTE =9,
58+ OP_SHL =10,
59+ OP_SHR =11,
60+ OP_ADD =12,
61+ OP_SUB =13,
62+ OP_MUL =14,
63+ OP_DIV =15,
64+ OP_REM =16
65+};
66+
67+#define LIB_MASK 0xFE00
68+#define LIB_STEP 0x0200
69+enum libs{
70+ LIB_SOUND =LIB_STEP*0,
71+ LIB_MUSICFUNC =LIB_STEP*1,
72+ LIB_MUSIC =LIB_STEP*2,
73+ LIB_SETDRAWCOUNT =LIB_STEP*3,
74+ LIB_DRAWCOUNT =LIB_STEP*4,
75+ LIB_PALETTE =LIB_STEP*5,
76+ LIB_GPALETTE =LIB_STEP*6,
77+ LIB_BGCOLOR =LIB_STEP*7,
78+ LIB_CURSOR =LIB_STEP*8,
79+ LIB_CLS =LIB_STEP*9,
80+ LIB_GCLS =LIB_STEP*10,
81+ LIB_COLOR =LIB_STEP*11,
82+ LIB_GCOLOR =LIB_STEP*12,
83+ LIB_KEYS =LIB_STEP*13,
84+ LIB_RESTORE =LIB_STEP*14,
85+ LIB_RESTORE2 =LIB_STEP*15,
86+ LIB_READ =LIB_STEP*16,
87+ LIB_MIDSTR =LIB_STEP*17,
88+ LIB_CLEAR =LIB_STEP*18,
89+ LIB_DIV0 =LIB_STEP*19,
90+ LIB_LETSTR =LIB_STEP*20,
91+ LIB_STRNCMP =LIB_STEP*21,
92+ LIB_RND =LIB_STEP*22,
93+ LIB_DEC =LIB_STEP*23,
94+ LIB_HEX =LIB_STEP*24,
95+ LIB_CHR =LIB_STEP*25,
96+ LIB_CONNECT_STRING =LIB_STEP*26,
97+ LIB_STRING =LIB_STEP*27,
98+ LIB_PRINTSTR =LIB_STEP*28,
99+ LIB_LABEL =LIB_STEP*29,
100+ LIB_DIM =LIB_STEP*30,
101+ LIB_VAL =LIB_STEP*31,
102+ LIB_INPUT =LIB_STEP*32,
103+ LIB_INKEY =LIB_STEP*33,
104+ LIB_USEPCG =LIB_STEP*34,
105+ LIB_PCG =LIB_STEP*35,
106+ LIB_SCROLL =LIB_STEP*36,
107+ LIB_WAIT =LIB_STEP*37,
108+ LIB_VAR_PUSH =LIB_STEP*38,
109+ LIB_VAR_POP =LIB_STEP*39,
110+ LIB_SYSTEM =LIB_STEP*40,
111+ LIB_SPRINTF =LIB_STEP*41,
112+ LIB_FLOAT =LIB_STEP*42,
113+ LIB_FLOATFUNCS =LIB_STEP*43,
114+ LIB_CREAD =LIB_STEP*44,
115+ LIB_USEGRAPHIC =LIB_STEP*45,
116+ LIB_GRAPHIC =LIB_STEP*46,
117+ LIB_WIDTH =LIB_STEP*47,
118+ LIB_FILE =LIB_STEP*48,
119+ LIB_PLAYWAVE =LIB_STEP*49,
120+ LIB_PLAYWAVEFUNC =LIB_STEP*50,
121+ LIB_DEBUG =LIB_STEP*127,
122+};
123+
124+// Note: OP_XXXX and FUNC_XXXX cannot be used simultaneously
125+#define FUNC_MASK 0x003F
126+#define FUNC_STEP 0x0001
127+enum functions{
128+ FUNC_FLOAT =FUNC_STEP*0,
129+ FUNC_INT =FUNC_STEP*1,
130+ FUNC_VALSHARP =FUNC_STEP*2,
131+ FUNC_SIN =FUNC_STEP*3,
132+ FUNC_COS =FUNC_STEP*4,
133+ FUNC_TAN =FUNC_STEP*5,
134+ FUNC_ASIN =FUNC_STEP*6,
135+ FUNC_ACOS =FUNC_STEP*7,
136+ FUNC_ATAN =FUNC_STEP*8,
137+ FUNC_ATAN2 =FUNC_STEP*9,
138+ FUNC_SINH =FUNC_STEP*10,
139+ FUNC_COSH =FUNC_STEP*11,
140+ FUNC_TANH =FUNC_STEP*12,
141+ FUNC_EXP =FUNC_STEP*13,
142+ FUNC_LOG =FUNC_STEP*14,
143+ FUNC_LOG10 =FUNC_STEP*15,
144+ FUNC_POW =FUNC_STEP*16,
145+ FUNC_SQRT =FUNC_STEP*17,
146+ FUNC_CEIL =FUNC_STEP*18,
147+ FUNC_FLOOR =FUNC_STEP*19,
148+ FUNC_FABS =FUNC_STEP*20,
149+ FUNC_MODF =FUNC_STEP*21,
150+ FUNC_FMOD =FUNC_STEP*22,
151+ FUNC_PSET =FUNC_STEP*23,
152+ FUNC_LINE =FUNC_STEP*24,
153+ FUNC_BOXFILL =FUNC_STEP*25,
154+ FUNC_CIRCLE =FUNC_STEP*26,
155+ FUNC_CIRCLEFILL =FUNC_STEP*27,
156+ FUNC_GPRINT =FUNC_STEP*28,
157+ FUNC_PUTBMP =FUNC_STEP*29,
158+ FUNC_PUTBMP2 =FUNC_STEP*30,
159+ FUNC_GCOLOR =FUNC_STEP*31,
160+ FUNC_POINT =FUNC_STEP*32,
161+ FUNC_FOPEN =FUNC_STEP*33,
162+ FUNC_FOPENST =FUNC_STEP*34,
163+ FUNC_FILE =FUNC_STEP*35,
164+ FUNC_FCLOSE =FUNC_STEP*36,
165+ FUNC_FINPUT =FUNC_STEP*37,
166+ FUNC_FPRINTSTR =FUNC_STEP*38,
167+ FUNC_FGET =FUNC_STEP*39,
168+ FUNC_FPUT =FUNC_STEP*40,
169+ FUNC_FSEEK =FUNC_STEP*41,
170+ FUNC_FTELL =FUNC_STEP*42,
171+ FUNC_FLEN =FUNC_STEP*43,
172+ FUNC_FSTRING =FUNC_STEP*44,
173+ FUNC_FGETC =FUNC_STEP*45,
174+ FUNC_FPUTC =FUNC_STEP*46,
175+ FUNC_FREMOVE =FUNC_STEP*47,
176+ FUNC_FEOF =FUNC_STEP*48,
177+ FUNC_FINIT =FUNC_STEP*49,
178+ // MAX 63
179+};
180+
181+/* Global vars (see globalvers.c) */
182+extern int g_intconst;
183+extern char g_valueisconst;
184+extern unsigned int g_rnd_seed;
185+extern unsigned int g_label;
186+extern int g_sdepth;
187+extern int g_maxsdepth;
188+extern enum variable g_lastvar;
189+extern char* g_source;
190+extern int g_srcpos;
191+extern int g_line;
192+extern int g_fileline;
193+extern int* g_object;
194+extern int g_objpos;
195+extern int* g_objmax;
196+extern const char* g_err_str[];
197+extern const unsigned char g_priority[];
198+extern enum operator g_last_op;
199+extern int g_end_addr;
200+extern int g_gp;
201+extern int g_s6;
202+extern char RAM[RAMSIZE];
203+extern unsigned int g_ex_data[EXCEPTION_DATA_SIZE/4];
204+extern int g_var_mem[ALLOC_BLOCK_NUM];
205+extern unsigned short g_var_pointer[ALLOC_BLOCK_NUM];
206+extern unsigned short g_var_size[ALLOC_BLOCK_NUM];
207+extern char g_temp_area_used;
208+extern int* g_heap_mem;
209+extern int g_max_mem;
210+extern char g_disable_break;
211+extern unsigned char* g_pcg_font;
212+extern char g_use_graphic;
213+extern unsigned short* g_graphic_area;
214+extern int* g_libparams;
215+extern int g_long_name_var_num;
216+extern int g_temp;
217+
218+/* Prototypes */
219+int get_gp(void);
220+int get_fp(void);
221+void start_program(void* addr, void* memory);
222+void shift_obj(int* src, int* dst, int len);
223+char* compile_line(void);
224+int nextCodeIs(char* str);
225+int endOfStatement();
226+
227+char* init_file(char* buff,char* appname);
228+void close_file();
229+void read_file(int blocklen);
230+char* compile_file();
231+
232+void err_break(void);
233+void err_music(char* str);
234+void err_data_not_found(void);
235+void err_str_complex(void);
236+void err_label_not_found(void);
237+void err_no_mem(void);
238+void err_div_zero(void);
239+void err_unkonwn(void);
240+void err_unexp_next(void);
241+void err_no_block(void);
242+void err_invalid_param(void);
243+void err_file(void);
244+void err_wave(void);
245+char* resolve_label(int s6);
246+
247+void set_sound(unsigned long* data, int flagsLR);
248+int musicRemaining(int flagsLR);
249+int waveRemaining(int mode);
250+void set_music(char* str, int flagsLR);
251+void stop_music(void);
252+void init_music(void);
253+void play_wave(char* filename, int start);
254+
255+char* statement(void);
256+char* gosub_statement();
257+char* graphic_statement(enum functions func);
258+char* fopen_statement_main(enum functions func);
259+char* fget_statement();
260+char* fput_statement();
261+char* fputc_statement();
262+char* fremove_statement();
263+
264+char* function(void);
265+char* str_function(void);
266+char* float_function(void);
267+
268+void call_library(void);
269+void reset_dataread();
270+
271+void free_temp_str(char* str);
272+void* alloc_memory(int size, int var_num);
273+void* calloc_memory(int size, int var_num);
274+void move_to_perm_block(int var_num);
275+void move_from_perm_block(int var_num);
276+int get_permanent_var_num(void);
277+
278+char* link(void);
279+char* get_label(void);
280+void* search_label(unsigned int label);
281+
282+char* get_string();
283+char* simple_string(void);
284+
285+char* get_operator(void);
286+char* get_floatOperator(void);
287+char* calculation(enum operator op);
288+char* calculation_float(enum operator op);
289+int lib_float(int ia0,int iv0, enum operator a1);
290+
291+int lib_file(enum functions func, int a0, int a1, int v0);
292+
293+char* get_dim_value(int i);
294+char* get_simple_value(void);
295+char* get_value();
296+char* get_floatOrValue();
297+char* get_stringFloatOrValue();
298+
299+void blue_screen(void);
300+
301+char* get_float();
302+
303+void cmpdata_init();
304+char* cmpdata_insert(unsigned char type, short data16, int* data, unsigned char num);
305+void cmpdata_reset();
306+int* cmpdata_find(unsigned char type);
307+int* cmpdata_findfirst(unsigned char type);
308+
309+int check_var_name();
310+int get_var_number();
311+int search_var_name(int nameint);
312+char* register_var_name(int nameint);
313+
314+
315+/* Error messages */
316+#define ERR_SYNTAX (char*)(g_err_str[0])
317+#define ERR_NE_BINARY (char*)(g_err_str[1])
318+#define ERR_NE_MEMORY (char*)(g_err_str[2])
319+#define ERR_DIV_0 (char*)(g_err_str[3])
320+#define ERR_NY_I (char*)(g_err_str[4])
321+#define ERR_LABEL_NF (char*)(g_err_str[5])
322+#define ERR_LABEL_LONG (char*)(g_err_str[6])
323+#define ERR_STR_COMPLEX (char*)(g_err_str[7])
324+#define ERR_DATA_NF (char*)(g_err_str[8])
325+#define ERR_UNKNOWN (char*)(g_err_str[9])
326+#define ERR_MUSIC (char*)(g_err_str[10])
327+#define ERR_MULTIPLE_LABEL (char*)(g_err_str[11])
328+#define ERR_BREAK (char*)(g_err_str[12])
329+#define ERR_UNEXP_NEXT (char*)(g_err_str[13])
330+#define ERR_NO_BLOCK (char*)(g_err_str[14])
331+#define ERR_GOSUB_ASH (char*)(g_err_str[15])
332+#define ERR_INVALID_BREAK (char*)(g_err_str[16])
333+#define ERR_INVALID_ELSEIF (char*)(g_err_str[17])
334+#define ERR_INVALID_PARAM (char*)(g_err_str[18])
335+#define ERR_FILE (char*)(g_err_str[19])
336+#define ERR_INVALID_VAR_NAME (char*)(g_err_str[20])
337+#define ERR_WAVE (char*)(g_err_str[21])
338+
339+/* comple data type numbers */
340+#define CMPDATA_RESERVED 0
341+#define CMPDATA_USEVAR 1
342+
343+/* Macros */
344+
345+// Skip blanc(s) in source code
346+#define next_position() while(g_source[g_srcpos]==' ') {g_srcpos++;}
347+
348+// Check if object area is not full.
349+#define check_obj_space(x) if (g_objmax<g_object+g_objpos+(x)) return ERR_NE_BINARY
350+
351+// Returns priority of operator
352+#define priority(x) (int)g_priority[(int)(x)]
353+
354+// Insert code for calling library
355+//02E0F809 jalr ra,s7
356+//24070000 addiu a3,zero,0000
357+#define call_lib_code(x) \
358+ check_obj_space(2);\
359+ g_object[g_objpos++]=0x02E0F809;\
360+ g_object[g_objpos++]=0x24070000|((x)&0x0000FFFF)
361+
362+// Division macro for unsigned long
363+// Valid for 31 bits for all cases and 32 bits for some cases
364+#define div32(x,y,z) ((((unsigned long long)((unsigned long)(x)))*((unsigned long long)((unsigned long)(y))))>>(z))
365+
366+// Divide by 9 (valid for 32 bits)
367+#define div9_32(x) div32(x,0xe38e38e4,35)
368+#define rem9_32(x) ((x)-9*div9_32(x))
369+
370+// Divide by 10 (valid for 32 bits)
371+#define div10_32(x) div32(x,0xcccccccd,35)
372+#define rem10_32(x) ((x)-10*div10_32(x))
373+
374+// Divide by 36 (valid for 32 bits)
375+#define div36_32(x) div32(x,0xe38e38e4,37)
376+#define rem36_32(x) (x-36*div36_32(x))
--- mips/branches/zoeaobjective/debug.c (nonexistent)
+++ mips/branches/zoeaobjective/debug.c (revision 271)
@@ -0,0 +1,245 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by K.Tanaka & Katsumi
4+ http://www.ze.em-net.ne.jp/~kenken/index.html
5+ http://hp.vector.co.jp/authors/VA016157/
6+*/
7+
8+#ifdef __DEBUG
9+
10+#include <xc.h>
11+#include "api.h"
12+#include "main.h"
13+#include "compiler.h"
14+
15+/*
16+ Enable following line when debugging binary object.
17+*/
18+//#include "debugdump.h"
19+
20+
21+// Pseudo reading config setting for debug mode
22+unsigned int g_DEVCFG1=0xFF7F4DDB;
23+
24+// Construct jump assembly in boot area.
25+const unsigned int _debug_boot[] __attribute__((address(0xBFC00000))) ={
26+ 0x0B401C00,// j 0x9d007000
27+ 0x00000000,// nop
28+};
29+
30+// Use DEBUG.HEX as file name of this program.
31+const unsigned char _debug_filename[] __attribute__((address(FILENAME_FLASH_ADDRESS))) ="DEBUG.HEX";
32+
33+static const char initext[];
34+static const char bastext[];
35+
36+static char* readtext;
37+static int filepos;
38+
39+/*
40+ Debug dump
41+ In debugdump.h:
42+ __DEBUGDUMP is defined.
43+ __DEBUGDUMP_FREEAREA is defined as start address of free area (1st argument of set_free_area() function)
44+ const unsigned char dump[] is initialized.
45+*/
46+#ifdef __DEBUGDUMP
47+int debugDump(){
48+ int i;
49+ for(i=0;i<sizeof dump;i++){
50+ RAM[i]=dump[i];
51+ }
52+
53+ g_objpos=(__DEBUGDUMP_FREEAREA-(unsigned int)g_object)/4;
54+
55+ // Initialize parameters
56+ g_pcg_font=0;
57+ g_use_graphic=0;
58+ g_graphic_area=0;
59+ clearscreen();
60+ setcursor(0,0,7);
61+
62+ printstr("BASIC "BASVER"\n");
63+ wait60thsec(15);
64+
65+ printstr("Compiling...");
66+
67+ // Initialize the other parameters
68+ // Random seed
69+ g_rnd_seed=0x92D68CA2; //2463534242
70+ // Clear variables
71+ for(i=0;i<ALLOC_BLOCK_NUM;i++){
72+ g_var_mem[i]=0;
73+ g_var_size[i]=0;
74+ }
75+ // Clear key input buffer
76+ for(i=0;i<256;i++){
77+ ps2keystatus[i]=0;
78+ }
79+ // Reset data/read.
80+ reset_dataread();
81+
82+ // Assign memory
83+ set_free_area((void*)(g_object+g_objpos),(void*)(&RAM[RAMSIZE]));
84+ // Execute program
85+ // Start program from the beginning of RAM.
86+ // Work area (used for A-Z values) is next to the object code area.
87+ start_program((void*)(&(RAM[0])),(void*)(&g_var_mem[0]));
88+ printstr("\nOK\n");
89+ g_use_graphic=0;
90+
91+ return 1;
92+}
93+#else
94+int debugDump(){
95+ return 0;
96+}
97+#endif
98+
99+/*
100+ Override libsdfsio functions.
101+ Here, don't use SD card, but the vertual files
102+ (initext[] and bastext[]) are used.
103+*/
104+
105+FSFILE fsfile;
106+
107+size_t FSfread(void *ptr, size_t size, size_t n, FSFILE *stream){
108+ char b;
109+ size_t ret=0;
110+ if (!readtext) return 0;
111+ while(b=readtext[filepos]){
112+ filepos++;
113+ ((char*)ptr)[ret]=b;
114+ ret++;
115+ if (n<=ret) break;
116+ }
117+ return ret;
118+}
119+FSFILE* FSfopen(const char * fileName, const char *mode){
120+ int i;
121+ for(i=0;i<13;i++){
122+ if (fileName[i]=='.') break;
123+ }
124+ if (i==13) {
125+ // Unknown file name
126+ // Force BAS file
127+ readtext=(char*)&bastext[0];
128+ } else if (fileName[i+1]=='I' && fileName[i+2]=='N' && fileName[i+3]=='I') {
129+ // INI file
130+ readtext=(char*)&initext[0];
131+ } else if (fileName[i+1]=='B' && fileName[i+2]=='A' && fileName[i+3]=='S') {
132+ // BAS file
133+ readtext=(char*)&bastext[0];
134+ // Try debugDump.
135+ if (debugDump()) return 0;
136+ } else {
137+ readtext=0;
138+ return 0;
139+ }
140+ filepos=0;
141+ return &fsfile;
142+}
143+int FSfeof( FSFILE * stream ){
144+ return readtext[filepos]?1:0;
145+}
146+int FSfclose(FSFILE *fo){
147+ return 0;
148+}
149+int FSInit(void){
150+ return 1;
151+}
152+int FSremove (const char * fileName){
153+ return 0;
154+}
155+size_t FSfwrite(const void *ptr, size_t size, size_t n, FSFILE *stream){
156+ return 0;
157+}
158+
159+int FindFirst (const char * fileName, unsigned int attr, SearchRec * rec){
160+ return 0;
161+}
162+int FindNext (SearchRec * rec){
163+ return 0;
164+}
165+int FSmkdir (char * path){
166+ return 0;
167+}
168+char * FSgetcwd (char * path, int numchars){
169+ return 0;
170+}
171+int FSchdir (char * path){
172+ return 0;
173+}
174+long FSftell (FSFILE * fo){
175+ return 0;
176+}
177+int FSfseek(FSFILE *stream, long offset, int whence){
178+ return 0;
179+}
180+/*
181+ ps2init() is not called.
182+ Instead, not_ps2init_but_init_Timer1() is called.
183+ Timer1 is used to update drawcount and drawing gloval variables.
184+*/
185+
186+int not_ps2init_but_init_Timer1(){
187+ PR1=0x0FFF;
188+ TMR1=0;
189+ IFS0bits.T1IF=0;
190+ T1CON=0x8000;
191+ // Timer1 interrupt: priority 4
192+ IPC1bits.T1IP=4;
193+ IPC1bits.T1IS=0;
194+ IEC0bits.T1IE=1;
195+
196+ return 0;
197+}
198+
199+#pragma interrupt timer1Int IPL4SOFT vector 4
200+
201+void timer1Int(){
202+ IFS0bits.T1IF=0;
203+ if (drawing) {
204+ drawing=0;
205+ drawcount++;
206+ } else {
207+ drawing=1;
208+ }
209+}
210+
211+/*
212+ initext[] and bastext[] are vertual files
213+ as "MACHIKAN.INI" and "DEBUG.BAS".
214+*/
215+
216+
217+static const char initext[]=
218+"#PRINT\n"
219+"#PRINT\n";
220+
221+
222+static const char bastext[]=
223+"CLS\n"
224+"print NOT(0);IN(0)\n"
225+"\n";
226+
227+/*
228+ Test function for constructing assemblies from C codes.
229+*/
230+
231+int _debug_test(int a0, int a1, int a2, int a3, int param4, int param5){
232+// if (a0<0xa0008192) return 0xa0000000;
233+ asm volatile("lw $sp,18($fp)");
234+ asm volatile("addiu $sp,$sp,2044");
235+ return a2+a3;
236+}
237+
238+/*
239+ Break point used for debugging object code.
240+
241+g_object[g_objpos++]=0x0000000d;// break 0x0
242+
243+*/
244+
245+#endif // __DEBUG
--- mips/branches/zoeaobjective/debug.h (nonexistent)
+++ mips/branches/zoeaobjective/debug.h (revision 271)
@@ -0,0 +1,30 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by K.Tanaka & Katsumi
4+ http://www.ze.em-net.ne.jp/~kenken/index.html
5+ http://hp.vector.co.jp/authors/VA016157/
6+*/
7+
8+#ifdef __DEBUG
9+
10+// Pseudo reading config setting for debug mode
11+extern unsigned int g_DEVCFG1;
12+#define DEVCFG1 g_DEVCFG1
13+
14+// Do not use PS/2 keyboard
15+#define ps2init() not_ps2init_but_init_Timer1()
16+int not_ps2init_but_init_Timer1();
17+
18+// Do not use asm("wait") but use asm("nop")
19+#undef WAIT
20+#define WAIT "nop"
21+
22+#endif // __DEBUG
23+
24+// key waiting macro
25+
26+#define debug_wait() lineinput((char*)&g_temp,3)
27+#define debug_wait_char(x) do {\
28+ printchar(x); \
29+ lineinput((char*)&g_temp,3);\
30+ } while(0)
--- mips/branches/zoeaobjective/error.c (nonexistent)
+++ mips/branches/zoeaobjective/error.c (revision 271)
@@ -0,0 +1,170 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by Katsumi.
4+ http://hp.vector.co.jp/authors/VA016157/
5+ kmorimatsu@users.sourceforge.jp
6+*/
7+
8+#include "compiler.h"
9+
10+const char* g_err_str[]={
11+ "Syntax error",
12+ "Not enough binary space",
13+ "Not enough memory",
14+ "Divided by zero",
15+ "Not yet implemented",
16+ "Label or line number not found: ",
17+ "Label too long or too short",
18+ "String too complexed",
19+ "Data not found",
20+ "Unknown error:",
21+ "Music syntax error:'",
22+ " found more than twice",
23+ "Break",
24+ "Unexpected NEXT or RETURN statement",
25+ "Cannot assign temporary block",
26+ "GOSUB fuction cannot be used after string-handling",
27+ "Invalid BREAK statement in line ",
28+ "Invalid ELSE/IF statement in line ",
29+ "Invalid parameter(s)",
30+ "File error",
31+ "Invalid variable name",
32+ "WAVE format error",
33+};
34+
35+char* resolve_label(int s6){
36+ static char str[7];
37+ int i,j;
38+ if (s6<65536) {
39+ // Line number
40+ for(i=0;i<5;i++){
41+ str[5-i]='0'+rem10_32(s6);
42+ s6=div10_32(s6);
43+ }
44+ str[6]=0x00;
45+ for(j=1;j<5;j++){
46+ if (str[j]!='0') break;
47+ }
48+ return (char*)(str+j);
49+ } else {
50+ // Label
51+ s6-=65536;
52+ str[6]=0x00;
53+ for(i=5;0<=i;i--){
54+ if (s6<36) {
55+ // First character must be A-Z, corresponding to 1-26 but not 10-35.
56+ // See get_label() for the detail.
57+ str[i]=s6-1+'A';
58+ break;
59+ } else {
60+ // From second, 0-9 corresponds to 0-9 and A-Z corresponds to 10-35.
61+ str[i]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[rem36_32(s6)];
62+ s6=div36_32(s6);
63+ }
64+ }
65+ return (char*)(str+i);
66+ }
67+}
68+
69+void pre_end_addr(int s6){
70+ int i,j;
71+ char str[7];
72+ // Cool down the system
73+ stop_music();
74+ // Resolve line and show it
75+ if (s6<0) s6=s6&0x7fffffff;
76+ g_label=s6;
77+ if (s6<65536) {
78+ // Line number
79+ printstr("\nIn line ");
80+ } else {
81+ // Label
82+ printstr("\nAfter label ");
83+ }
84+ printstr(resolve_label(s6));
85+ asm volatile("la $v0,%0"::"i"(&g_end_addr));
86+ asm volatile("lw $v0,0($v0)");
87+ asm volatile("nop");
88+ asm volatile("jr $v0");
89+}
90+
91+#define end_exec() \
92+ asm volatile("addu $a0,$s6,$zero");\
93+ asm volatile("j pre_end_addr")
94+
95+void err_break(void){
96+ stop_music();
97+ printstr(ERR_BREAK);
98+ end_exec();
99+}
100+
101+void err_data_not_found(void){
102+ printstr(ERR_DATA_NF);
103+ end_exec();
104+}
105+
106+void err_label_not_found(void){
107+ printstr(ERR_LABEL_NF);
108+ printstr(resolve_label(g_label));
109+ printstr("\n");
110+ end_exec();
111+}
112+
113+void err_div_zero(void){
114+ printstr(ERR_DIV_0);
115+ end_exec();
116+}
117+
118+void err_no_mem(void){
119+ printstr(ERR_NE_MEMORY);
120+ end_exec();
121+}
122+
123+void err_str_complex(void){
124+ printstr(ERR_STR_COMPLEX);
125+ end_exec();
126+}
127+
128+void err_unknown(void){
129+ asm volatile("la $v0,%0"::"i"(&g_temp));
130+ asm volatile("sw $ra,0($v0)");
131+ printstr(ERR_UNKNOWN);
132+ printhex32(g_temp);
133+ end_exec();
134+}
135+
136+void err_music(char* str){
137+ printstr(ERR_MUSIC);
138+ printstr(str);
139+ printstr("'\n");
140+ // Restore s6 from g_s6
141+ asm volatile("la $s6,%0"::"i"(&g_s6));
142+ asm volatile("lw $s6,0($s6)");
143+ end_exec();
144+}
145+
146+void err_unexp_next(void){
147+ printstr(ERR_UNEXP_NEXT);
148+ end_exec();
149+}
150+
151+void err_no_block(void){
152+ printstr(ERR_NO_BLOCK);
153+ end_exec();
154+}
155+
156+void err_invalid_param(void){
157+ printstr(ERR_INVALID_PARAM);
158+ end_exec();
159+}
160+
161+void err_file(void){
162+ printstr(ERR_FILE);
163+ end_exec();
164+}
165+
166+void err_wave(void){
167+ printstr(ERR_WAVE);
168+ end_exec();
169+}
170+
--- mips/branches/zoeaobjective/function.c (nonexistent)
+++ mips/branches/zoeaobjective/function.c (revision 271)
@@ -0,0 +1,588 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by Katsumi.
4+ http://hp.vector.co.jp/authors/VA016157/
5+ kmorimatsu@users.sourceforge.jp
6+*/
7+
8+#include "compiler.h"
9+#include "api.h"
10+
11+char* music_function(){
12+ char* err;
13+ next_position();
14+ if (g_source[g_srcpos]==')') {
15+ check_obj_space(1);
16+ g_object[g_objpos++]=0x34020003; //ori v0,zero,0x03
17+ } else {
18+ err=get_value();
19+ if (err) return err;
20+ }
21+ call_lib_code(LIB_MUSICFUNC);
22+ return 0;
23+}
24+
25+char* read_function(){
26+ call_lib_code(LIB_READ);
27+ return 0;
28+}
29+
30+char* cread_function(){
31+ call_lib_code(LIB_CREAD);
32+ return 0;
33+}
34+
35+char* gosub_function(){
36+ // Check if garbage collection has been done.
37+ // This check is required because the used temporary area would be changed
38+ // in sub routine.
39+ if (g_temp_area_used) return ERR_GOSUB_ASH;
40+ return gosub_statement();
41+}
42+char* strncmp_function(){
43+ char* err;
44+ err=get_string();
45+ if (err) return err;
46+ check_obj_space(2);
47+ g_object[g_objpos++]=0x27BDFFF8; // addiu sp,sp,-8
48+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
49+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
50+ g_srcpos++;
51+ err=get_string();
52+ if (err) return err;
53+ check_obj_space(1);
54+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
55+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
56+ g_srcpos++;
57+ err=get_value();
58+ if (err) return err;
59+ call_lib_code(LIB_STRNCMP);
60+ check_obj_space(1);
61+ g_object[g_objpos++]=0x27BD0008; // addiu sp,sp,8
62+ return 0;
63+}
64+char* len_function(){
65+ char* err;
66+ err=get_string();
67+ if (err) return err;
68+ check_obj_space(5);
69+ g_object[g_objpos++]=0x2443FFFF; // addiu v1,v0,-1
70+ // loop:
71+ g_object[g_objpos++]=0x80640001; // lb a0,1(v1)
72+ g_object[g_objpos++]=0x1480FFFE; // bne a0,zero,loop
73+ g_object[g_objpos++]=0x24630001; // addiu v1,v1,1
74+ g_object[g_objpos++]=0x00621023; // subu v0,v1,v0
75+ return 0;
76+}
77+
78+char* asc_function(){
79+ char* err;
80+ err=get_string();
81+ if (err) return err;
82+ check_obj_space(1);
83+ g_object[g_objpos++]=0x90420000; // lbu v0,0(v0)
84+ return 0;
85+}
86+
87+char* val_function(){
88+ char* err;
89+ err=get_string();
90+ if (err) return err;
91+ call_lib_code(LIB_VAL);
92+ return 0;
93+}
94+
95+char* peek_function(){
96+ char* err;
97+ err=get_value();
98+ if (err) return err;
99+ check_obj_space(1);
100+ g_object[g_objpos++]=0x90420000; // lbu v0,0(v0)
101+ return 0;
102+}
103+
104+char* sgn_function(){
105+ char* err;
106+ err=get_value();
107+ if (err) return err;
108+ check_obj_space(5);
109+ g_object[g_objpos++]=0x10400004; // beq v0,zero,end
110+ g_object[g_objpos++]=0x24030001; // addiu v1,zero,1
111+ g_object[g_objpos++]=0x1C400002; // bgtz v0,end
112+ g_object[g_objpos++]=0x00601021; // addu v0,v1,zero
113+ g_object[g_objpos++]=0x00031023; // subu v0,zero,v1
114+ // end:
115+ return 0;
116+}
117+
118+char* abs_function(){
119+ char* err;
120+ err=get_value();
121+ if (err) return err;
122+ check_obj_space(3);
123+ g_object[g_objpos++]=0x00021FC3; //sra v1,v0,0x1f
124+ g_object[g_objpos++]=0x00621026; //xor v0,v1,v0
125+ g_object[g_objpos++]=0x00431023; //subu v0,v0,v1
126+ return 0;
127+}
128+
129+char* not_function(){
130+ char* err;
131+ err=get_value();
132+ if (err) return err;
133+ check_obj_space(1);
134+ g_object[g_objpos++]=0x2C420001; //sltiu v0,v0,1
135+ return 0;
136+}
137+
138+char* rnd_function(){
139+ call_lib_code(LIB_RND);
140+ return 0;
141+}
142+
143+
144+char* chr_function(void){
145+ char* err;
146+ err=get_value();
147+ if (err) return err;
148+ call_lib_code(LIB_CHR);
149+ return 0;
150+}
151+char* hex_function(void){
152+ char* err;
153+ err=get_value();
154+ if (err) return err;
155+ if (g_source[g_srcpos]==',') {
156+ // Second argument found.
157+ // Get is as $a0.
158+ g_srcpos++;
159+ check_obj_space(2);
160+ g_object[g_objpos++]=0x27BDFFFC; //addiu sp,sp,-4
161+ g_object[g_objpos++]=0xAFA20004; //sw v0,4(sp)
162+ err=get_value();
163+ if (err) return err;
164+ check_obj_space(3);
165+ g_object[g_objpos++]=0x00022021; //a0,zero,v0
166+ g_object[g_objpos++]=0x8FA20004; //lw v0,4(sp)
167+ g_object[g_objpos++]=0x27BD0004; //addiu sp,sp,4
168+ } else {
169+ // Second argument not found.
170+ // Set $a0 to 0.
171+ check_obj_space(1);
172+ g_object[g_objpos++]=0x24040000; //addiu a0,zero,0
173+ }
174+ call_lib_code(LIB_HEX);
175+ return 0;
176+}
177+
178+char* dec_function(void){
179+ char* err;
180+ err=get_value();
181+ if (err) return err;
182+ call_lib_code(LIB_DEC);
183+ return 0;
184+}
185+
186+char* keys_function(void){
187+ char* err;
188+ next_position();
189+ if (g_source[g_srcpos]==')') {
190+ check_obj_space(1);
191+ g_object[g_objpos++]=0x3402003F; //ori v0,zero,0x3f
192+ } else {
193+ err=get_value();
194+ if (err) return err;
195+ }
196+ call_lib_code(LIB_KEYS);
197+ return 0;
198+}
199+
200+char* tvram_function(void){
201+ char* err;
202+ int i;
203+ next_position();
204+ if (g_source[g_srcpos]==')') {
205+ i=(int)(&TVRAM[0]);
206+ i-=g_gp;
207+ check_obj_space(1);
208+ g_object[g_objpos++]=0x27820000|(i&0x0000FFFF); // addiu v0,gp,xxxx
209+ } else {
210+ err=get_value();
211+ if (err) return err;
212+ i=(int)(&TVRAM[0]);
213+ i-=g_gp;
214+ check_obj_space(3);
215+ g_object[g_objpos++]=0x27830000|(i&0x0000FFFF); // addiu v1,gp,xxxx
216+ g_object[g_objpos++]=0x00621821; // addu v1,v1,v0
217+ g_object[g_objpos++]=0x90620000; // lbu v0,0(v1)
218+ }
219+ return 0;
220+}
221+
222+char* drawcount_function(void){
223+ call_lib_code(LIB_DRAWCOUNT);
224+ return 0;
225+}
226+
227+char* input_function(void){
228+ call_lib_code(LIB_INPUT);
229+ return 0;
230+}
231+
232+char* inkey_function(void){
233+ char* err;
234+ next_position();
235+ if (g_source[g_srcpos]==')') {
236+ check_obj_space(1);
237+ g_object[g_objpos++]=0x34020000; //ori v0,zero,0x00
238+ } else {
239+ err=get_value();
240+ if (err) return err;
241+ }
242+ call_lib_code(LIB_INKEY);
243+ return 0;
244+}
245+
246+char* args_function(void){
247+ char* err;
248+ int i;
249+ err=get_value();
250+ if (err) return err;
251+ i=g_object[g_objpos-1];
252+ if ((i>>16)==0x3402) {
253+ // Previous object is "ori v0,zero,xxxx".
254+ i&=0xffff;
255+ i=(i+1)<<2;
256+ g_object[g_objpos-1]=0x8EA20000|i; // lw v0,xx(s5)
257+ } else {
258+ check_obj_space(3);
259+ g_object[g_objpos++]=0x00021080; // sll v0,v0,0x2
260+ g_object[g_objpos++]=0x02A21021; // addu v0,s5,v0
261+ g_object[g_objpos++]=0x8C420004; // lw v0,4(v0)
262+ }
263+ return 0;
264+}
265+
266+char* system_function(void){
267+ char* err;
268+ err=get_value();
269+ if (err) return err;
270+ g_object[g_objpos++]=0x00402021; // addu a0,v0,zero
271+ call_lib_code(LIB_SYSTEM);
272+ return 0;
273+}
274+
275+char* sprintf_function(void){
276+ char* err;
277+ err=get_string();
278+ if (err) return err;
279+ next_position();
280+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
281+ g_srcpos++;
282+ check_obj_space(2);
283+ g_object[g_objpos++]=0x27BDFFFC; //addiu sp,sp,-4
284+ g_object[g_objpos++]=0xAFA20004; //sw v0,4(sp)
285+ err=get_float();
286+ if (err) return err;
287+ check_obj_space(3);
288+ g_object[g_objpos++]=0x00022021; //addu a0,zero,v0
289+ g_object[g_objpos++]=0x8FA20004; //lw v0,4(sp)
290+ g_object[g_objpos++]=0x27BD0004; //addiu sp,sp,4
291+ call_lib_code(LIB_SPRINTF);
292+ return 0;
293+}
294+
295+char* floatstr_function(void){
296+ char* err;
297+ err=get_float();
298+ if (err) return err;
299+ check_obj_space(2);
300+ g_object[g_objpos++]=0x00022021; //addu a0,zero,v0
301+ g_object[g_objpos++]=0x34020000; //ori v0,zero,0x0000
302+ call_lib_code(LIB_SPRINTF);
303+ return 0;
304+}
305+
306+char* floatsharp_function(void){
307+ char* err;
308+ err=get_value();
309+ if (err) return err;
310+ call_lib_code(LIB_FLOATFUNCS | FUNC_FLOAT);
311+ return 0;
312+}
313+
314+char* valsharp_function(void){
315+ char* err;
316+ err=get_string();
317+ if (err) return err;
318+ call_lib_code(LIB_FLOATFUNCS | FUNC_VALSHARP);
319+ return 0;
320+}
321+
322+char* int_function(void){
323+ char* err;
324+ err=get_float();
325+ if (err) return err;
326+ call_lib_code(LIB_FLOATFUNCS | FUNC_INT);
327+ return 0;
328+}
329+
330+char* fseek_function(){
331+ call_lib_code(LIB_FILE | FUNC_FTELL);
332+ return 0;
333+}
334+
335+char* flen_function(){
336+ call_lib_code(LIB_FILE | FUNC_FLEN);
337+ return 0;
338+}
339+
340+char* fgetc_function(){
341+ call_lib_code(LIB_FILE | FUNC_FGETC);
342+ return 0;
343+}
344+
345+char* finput_function(){
346+ char* err;
347+ next_position();
348+ if (g_source[g_srcpos]!=')') {
349+ err=get_value();
350+ if (err) return err;
351+ } else {
352+ // Parameter will be zero if not defined
353+ check_obj_space(1);
354+ g_object[g_objpos++]=0x34020000; // ori v0,zero,0
355+ }
356+ call_lib_code(LIB_FILE | FUNC_FINPUT);
357+ return 0;
358+}
359+
360+char* feof_function(){
361+ call_lib_code(LIB_FILE | FUNC_FEOF);
362+ return 0;
363+}
364+
365+char* playwave_function(){
366+ char* err;
367+ next_position();
368+ if (g_source[g_srcpos]!=')') {
369+ // Get param
370+ err=get_value();
371+ if (err) return err;
372+ } else {
373+ // If parameter is omitted, use 0.
374+ check_obj_space(1);
375+ g_object[g_objpos++]=0x24020000; // addiu v0,zero,0
376+ }
377+ call_lib_code(LIB_PLAYWAVEFUNC);
378+ return 0;
379+}
380+
381+char* float_constant(float val){
382+ volatile int i;
383+ ((float*)(&i))[0]=val;
384+ if (i&0xFFFF0000) {
385+ // 32 bit
386+ check_obj_space(2);
387+ g_object[g_objpos++]=0x3C020000|((i>>16)&0x0000FFFF); // lui v0,xxxx
388+ g_object[g_objpos++]=0x34420000|(i&0x0000FFFF); // ori v0,v0,xxxx
389+ } else {
390+ // 16 bit
391+ check_obj_space(1);
392+ g_object[g_objpos++]=0x34020000|(i&0x0000FFFF); // ori v0,zero,xxxx
393+ }
394+ return 0;
395+}
396+
397+char* float_1param_function(enum functions func){
398+ char* err;
399+ err=get_float();
400+ if (err) return err;
401+ call_lib_code(LIB_FLOATFUNCS | func);
402+ return 0;
403+}
404+
405+char* float_2param_function(enum functions func){
406+ char* err;
407+ err=get_float();
408+ if (err) return err;
409+ next_position();
410+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
411+ g_srcpos++;
412+ check_obj_space(2);
413+ g_object[g_objpos++]=0x27BDFFFC; //addiu sp,sp,-4
414+ g_object[g_objpos++]=0xAFA20004; //sw v0,4(sp)
415+ err=get_float();
416+ if (err) return err;
417+ check_obj_space(3);
418+ g_object[g_objpos++]=0x00022021; //addu a0,zero,v0
419+ g_object[g_objpos++]=0x8FA20004; //lw v0,4(sp)
420+ g_object[g_objpos++]=0x27BD0004; //addiu sp,sp,4
421+ call_lib_code(LIB_FLOATFUNCS | func);
422+ return 0;
423+}
424+
425+char* float_function(void){
426+ char* err;
427+ if (nextCodeIs("FLOAT#(")) {
428+ err=floatsharp_function();
429+ } else if (nextCodeIs("VAL#(")) {
430+ err=valsharp_function();
431+ } else if (nextCodeIs("SIN#(")) {
432+ err=float_1param_function(FUNC_SIN);
433+ } else if (nextCodeIs("COS#(")) {
434+ err=float_1param_function(FUNC_COS);
435+ } else if (nextCodeIs("TAN#(")) {
436+ err=float_1param_function(FUNC_TAN);
437+ } else if (nextCodeIs("ASIN#(")) {
438+ err=float_1param_function(FUNC_ASIN);
439+ } else if (nextCodeIs("ACOS#(")) {
440+ err=float_1param_function(FUNC_ACOS);
441+ } else if (nextCodeIs("ATAN#(")) {
442+ err=float_1param_function(FUNC_ATAN);
443+ } else if (nextCodeIs("ATAN2#(")) {
444+ err=float_2param_function(FUNC_ATAN2);
445+ } else if (nextCodeIs("SINH#(")) {
446+ err=float_1param_function(FUNC_SINH);
447+ } else if (nextCodeIs("COSH#(")) {
448+ err=float_1param_function(FUNC_COSH);
449+ } else if (nextCodeIs("TANH#(")) {
450+ err=float_1param_function(FUNC_TANH);
451+ } else if (nextCodeIs("EXP#(")) {
452+ err=float_1param_function(FUNC_EXP);
453+ } else if (nextCodeIs("LOG#(")) {
454+ err=float_1param_function(FUNC_LOG);
455+ } else if (nextCodeIs("LOG10#(")) {
456+ err=float_1param_function(FUNC_LOG10);
457+ } else if (nextCodeIs("POW#(")) {
458+ err=float_2param_function(FUNC_POW);
459+ } else if (nextCodeIs("SQRT#(")) {
460+ err=float_1param_function(FUNC_SQRT);
461+ } else if (nextCodeIs("CEIL#(")) {
462+ err=float_1param_function(FUNC_CEIL);
463+ } else if (nextCodeIs("FLOOR#(")) {
464+ err=float_1param_function(FUNC_FLOOR);
465+ } else if (nextCodeIs("FABS#(")) {
466+ err=float_1param_function(FUNC_FABS);
467+ } else if (nextCodeIs("MODF#(")) {
468+ err=float_1param_function(FUNC_MODF);
469+ } else if (nextCodeIs("FMOD#(")) {
470+ err=float_2param_function(FUNC_FMOD);
471+ } else if (nextCodeIs("GOSUB#(")) {
472+ err=gosub_function();
473+ } else if (nextCodeIs("ARGS#(")) {
474+ err=args_function();
475+ } else if (nextCodeIs("PI#")) {
476+ return float_constant(3.141593);
477+ } else {
478+ return ERR_SYNTAX;
479+ }
480+ if (err) return err;
481+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
482+ g_srcpos++;
483+ return 0;
484+}
485+
486+static const void* str_func_list[]={
487+ "CHR$(",chr_function,
488+ "HEX$(",hex_function,
489+ "DEC$(",dec_function,
490+ "INPUT$(",input_function,
491+ "GOSUB$(",gosub_function,
492+ "ARGS$(",args_function,
493+ "READ$(",read_function,
494+ "SPRINTF$(",sprintf_function,
495+ "FLOAT$(",floatstr_function,
496+ "SYSTEM$(",system_function,
497+ "FINPUT$(",finput_function,
498+ // Additional functions follow
499+ ADDITIONAL_STR_FUNCTIONS
500+};
501+
502+char* str_function(void){
503+ char* err;
504+ int i;
505+ char* (*f)();
506+ // Seek the function
507+ for (i=0;i<sizeof(str_func_list)/sizeof(str_func_list[0]);i+=2){
508+ if (nextCodeIs((char*)str_func_list[i])) break;
509+ }
510+ if (i<sizeof(str_func_list)/sizeof(str_func_list[0])) {
511+ // Function found. Call it.
512+ f=str_func_list[i+1];
513+ err=f();
514+ } else {
515+ return ERR_SYNTAX;
516+ }
517+ if (err) return err;
518+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
519+ g_srcpos++;
520+ return 0;
521+}
522+
523+// Aliases follow
524+
525+char* gcolor_function(){
526+ return graphic_statement(FUNC_GCOLOR);
527+}
528+
529+char* fopen_function(){
530+ return fopen_statement_main(FUNC_FOPEN);
531+}
532+
533+static const void* int_func_list[]={
534+ "NOT(",not_function,
535+ "DRAWCOUNT(",drawcount_function,
536+ "MUSIC(",music_function,
537+ "TVRAM(",tvram_function,
538+ "KEYS(",keys_function,
539+ "READ(",read_function,
540+ "CREAD(",cread_function,
541+ "GOSUB(",gosub_function,
542+ "STRNCMP(",strncmp_function,
543+ "PEEK(",peek_function,
544+ "LEN(",len_function,
545+ "ASC(",asc_function,
546+ "SGN(",sgn_function,
547+ "ABS(",abs_function,
548+ "RND(",rnd_function,
549+ "VAL(",val_function,
550+ "INKEY(",inkey_function,
551+ "ARGS(",args_function,
552+ "SYSTEM(",system_function,
553+ "INT(",int_function,
554+ "GCOLOR(",gcolor_function,
555+ "FOPEN(",fopen_function,
556+ "FSEEK(",fseek_function,
557+ "FLEN(",flen_function,
558+ "FGET(",fget_statement,
559+ "FPUT(",fput_statement,
560+ "FGETC(",fgetc_function,
561+ "FPUTC(",fputc_statement,
562+ "FREMOVE(",fremove_statement,
563+ "FEOF(",feof_function,
564+ "PLAYWAVE(",playwave_function,
565+ // Additional functions follow
566+ ADDITIONAL_INT_FUNCTIONS
567+};
568+
569+char* function(void){
570+ char* err;
571+ int i;
572+ char* (*f)();
573+ // Seek the function
574+ for (i=0;i<sizeof(int_func_list)/sizeof(int_func_list[0]);i+=2){
575+ if (nextCodeIs((char*)int_func_list[i])) break;
576+ }
577+ if (i<sizeof(int_func_list)/sizeof(int_func_list[0])) {
578+ // Function found. Call it.
579+ f=int_func_list[i+1];
580+ err=f();
581+ } else {
582+ return ERR_SYNTAX;
583+ }
584+ if (err) return err;
585+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
586+ g_srcpos++;
587+ return 0;
588+}
--- mips/branches/zoeaobjective/library.c (nonexistent)
+++ mips/branches/zoeaobjective/library.c (revision 271)
@@ -0,0 +1,1085 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by Katsumi.
4+ http://hp.vector.co.jp/authors/VA016157/
5+ kmorimatsu@users.sourceforge.jp
6+*/
7+
8+#include <xc.h>
9+#include "main.h"
10+#include "compiler.h"
11+#include "api.h"
12+#include "keyinput.h"
13+#include "stdlib.h"
14+#include "math.h"
15+
16+/*
17+ Local global variables used for graphic
18+ */
19+
20+static int g_gcolor=7;
21+static int g_prev_x=0;
22+static int g_prev_y=0;
23+
24+int lib_read(int mode, unsigned int label){
25+ unsigned int i,code,code2;
26+ static unsigned int pos=0;
27+ static unsigned int in_data=0;
28+ static unsigned char skip=0;
29+ if (label) {
30+ // RESTORE function
31+ switch(mode){
32+ case 0:
33+ // label is label data
34+ i=(int)search_label(label);
35+ if (!i) {
36+ err_data_not_found();
37+ return 0;
38+ }
39+ break;
40+ case 1:
41+ // label is pointer
42+ i=label;
43+ break;
44+ case 2:
45+ default:
46+ // Reset data/read
47+ pos=0;
48+ in_data=0;
49+ skip=0;
50+ return 0;
51+ }
52+ i-=(int)(&g_object[0]);
53+ pos=i/4;
54+ in_data=0;
55+ }
56+ // Get data
57+ if (in_data==0) {
58+ for(i=pos;i<g_objpos;i++){
59+ code=g_object[i];
60+ code2=g_object[i+1];
61+ if ((code&0xFFFF0000)!=0x04110000) continue;
62+ // "bgezal zero," assembly found.
63+ // Check if 0x00000020,0x00000021,0x00000022, or 0x00000023 follows
64+ if ((code2&0xfffffffc)!=0x00000020) {// add/addu/sub/subu zero,zero,zero
65+ // If not, skip following block (it's strig).
66+ i+=code&0x0000FFFF;
67+ continue;
68+ }
69+ // DATA region found.
70+ in_data=(code&0x0000FFFF)-1;
71+ pos=i+2;
72+ skip=code2&0x03;
73+ break;
74+ }
75+ if (g_objpos<=i) {
76+ err_data_not_found();
77+ return 0;
78+ }
79+ }
80+ if (label) {
81+ // RESTORE function. Return pointer.
82+ return ((int)&g_object[pos])+skip;
83+ } else {
84+ switch(mode){
85+ case 0:
86+ // READ() function
87+ in_data--;
88+ return g_object[pos++];
89+ case 1:
90+ default:
91+ // CREAD() function
92+ i=g_object[pos];
93+ i>>=skip*8;
94+ i&=0xff;
95+ if ((++skip)==4) {
96+ skip=0;
97+ in_data--;
98+ pos++;
99+ }
100+ return i;
101+ }
102+ }
103+}
104+
105+void reset_dataread(){
106+ lib_read(2,1);
107+}
108+
109+char* lib_midstr(int var_num, int pos, int len){
110+ int i;
111+ char* str;
112+ char* ret;
113+ if (0<=pos) {
114+ // String after "pos" position.
115+ str=(char*)(g_var_mem[var_num]+pos);
116+ } else {
117+ // String right "pos" characters.
118+ // Determine length
119+ str=(char*)g_var_mem[var_num];
120+ for(i=0;str[i];i++);
121+ if (0<=(i+pos)) {
122+ str=(char*)(g_var_mem[var_num]+i+pos);
123+ }
124+ }
125+ if (len<0) {
126+ // Length is not specified.
127+ // Return the string to the end.
128+ return str;
129+ }
130+ // Length is specified.
131+ // Construct temporary string containing specified number of characters.
132+ ret=alloc_memory((len+1+3)/4,-1);
133+ // Copy string.
134+ for(i=0;(ret[i]=str[i])&&(i<len);i++);
135+ ret[len]=0x00;
136+ return ret;
137+}
138+
139+void lib_clear(void){
140+ int i;
141+ // All variables (including temporary and permanent ones) will be integer 0
142+ for(i=0;i<ALLOC_BLOCK_NUM;i++){
143+ g_var_mem[i]=0;
144+ }
145+ // Clear memory allocation area
146+ for(i=0;i<ALLOC_BLOCK_NUM;i++){
147+ g_var_size[i]=0;
148+ }
149+ // Cancel PCG
150+ stopPCG();
151+ g_pcg_font=0;
152+ // Stop using graphic
153+ g_use_graphic=1; // Force set_graphmode(0) (see usegraphic() function)
154+ usegraphic(0);
155+}
156+
157+void lib_let_str(char* str, int var_num){
158+ int begin,end,size;
159+ // Save pointer
160+ g_var_mem[var_num]=(int)str;
161+ // Determine size
162+ for(size=0;str[size];size++);
163+ // Check if str is in heap area.
164+ begin=(int)str;
165+ end=(int)(&str[size]);
166+ if (begin<(int)(&g_heap_mem[0]) || (int)(&g_heap_mem[g_max_mem])<=end) {
167+ // String is not within allcated block
168+ return;
169+ }
170+ // Str is in heap area. Calculate values stored in heap data dimension
171+ begin-=(int)(&g_heap_mem[0]);
172+ begin>>=2;
173+ end-=(int)(&g_heap_mem[0]);
174+ end>>=2;
175+ size=end-begin+1;
176+ g_var_pointer[var_num]=begin;
177+ g_var_size[var_num]=size;
178+}
179+
180+int lib_rnd(){
181+ int y;
182+ y=g_rnd_seed;
183+ y = y ^ (y << 13);
184+ y = y ^ (y >> 17);
185+ y = y ^ (y << 5);
186+ g_rnd_seed=y;
187+ return y&0x7fff;
188+}
189+
190+char* lib_chr(int num){
191+ char* str;
192+ str=alloc_memory(1,-1);
193+ str[0]=num&0x000000FF;
194+ str[1]=0x00;
195+ return str;
196+}
197+
198+char* lib_dec(int num){
199+ char* str;
200+ int i,j,minus;
201+ char b[12];
202+ b[11]=0x00;
203+ if (num<0) {
204+ minus=1;
205+ num=0-num;
206+ } else {
207+ minus=0;
208+ }
209+ for (i=10;0<i;i--) {
210+ if (num==0 && i<10) break;
211+ b[i]='0'+rem10_32(num);
212+ num=div10_32(num);
213+ }
214+ if (minus) {
215+ b[i]='-';
216+ } else {
217+ i++;
218+ }
219+ str=alloc_memory(3,-1);
220+ for(j=0;str[j]=b[i++];j++);
221+ return str;
222+}
223+
224+char* lib_hex(int num, int width){
225+ char* str;
226+ int i,j,minus;
227+ char b[8];
228+ str=alloc_memory(3,-1);
229+ for(i=0;i<8;i++){
230+ b[i]="0123456789ABCDEF"[(num>>(i<<2))&0x0F];
231+ }
232+ // Width must be between 0 and 8;
233+ if (width<0||8<width) width=8;
234+ if (width==0) {
235+ // Width not asigned. Use minimum width.
236+ for(i=7;0<i;i--){
237+ if ('0'<b[i]) break;
238+ }
239+ } else {
240+ // Constant width
241+ i=width-1;
242+ }
243+ // Copy string to allocated block.
244+ for(j=0;0<=i;i--){
245+ str[j++]=b[i];
246+ }
247+ str[j]=0x00;
248+ return str;
249+}
250+
251+char* lib_connect_string(char* str1, char* str2){
252+ int i,j;
253+ char b;
254+ char* result;
255+ // Determine total length
256+ for(i=0;str1[i];i++);
257+ for(j=0;str2[j];j++);
258+ // Allocate a block for new string
259+ result=alloc_memory((i+j+1+3)/4,-1);
260+ // Create connected strings
261+ for(i=0;b=str1[i];i++) result[i]=b;
262+ for(j=0;b=str2[j];j++) result[i+j]=b;
263+ result[i+j]=0x00;
264+ free_temp_str(str1);
265+ free_temp_str(str2);
266+ return result;
267+}
268+
269+void lib_string(int mode){
270+ int i;
271+ switch(mode){
272+ case 0:
273+ // CR
274+ printchar('\n');
275+ return;
276+ case 1:
277+ // ,
278+ printcomma();
279+ return;
280+ default:
281+ return;
282+ }
283+}
284+
285+void* lib_label(unsigned int label){
286+ // This routine is used to jump to address dynamically determined
287+ // in the code; for example: "GOTO 100+I"
288+ unsigned int i,code,search;
289+ void* ret;
290+ if (label&0xFFFF0000) {
291+ // Label is not supported.
292+ // Line number must bs less than 65536.
293+ err_label_not_found();
294+ } else {
295+ // Line number
296+ ret=search_label(label);
297+ if (ret) return ret;
298+ // Line number not found.
299+ err_label_not_found();
300+ }
301+}
302+
303+int lib_keys(int mask){
304+ int keys;
305+ keys=readbuttons();
306+ keys=
307+ ((keys&KEYUP)? 0:1)|
308+ ((keys&KEYDOWN)? 0:2)|
309+ ((keys&KEYLEFT)? 0:4)|
310+ ((keys&KEYRIGHT)? 0:8)|
311+ ((keys&KEYSTART)? 0:16)|
312+ ((keys&KEYFIRE)? 0:32);
313+ return mask&keys;
314+}
315+
316+int lib_val(char* str){
317+ int i;
318+ int val=0;
319+ int sign=1;
320+ char b;
321+ // Skip blanc
322+ for(i=0;0<=str[i] && str[i]<0x21;i++);
323+ // Skip '+'
324+ if (str[i]=='+') i++;
325+ // Check '-'
326+ if (str[i]=='-') {
327+ sign=-1;
328+ i++;
329+ }
330+ // Check '0x' or '$'
331+ if (str[i]=='$' || str[i]=='0' && (str[i+1]=='x' || str[i+1]=='X')) {
332+ // Hexadecimal
333+ if (str[i++]=='0') i++;
334+ while(1) {
335+ b=str[i++];
336+ if ('0'<=b && b<='9') {
337+ val<<=4;
338+ val+=b-'0';
339+ } else if ('a'<=b && b<='f') {
340+ val<<=4;
341+ val+=b-'a'+10;
342+ } else if ('A'<=b && b<='F') {
343+ val<<=4;
344+ val+=b-'A'+10;
345+ } else {
346+ break;
347+ }
348+ }
349+ } else {
350+ // Decimal
351+ while(1) {
352+ b=str[i++];
353+ if ('0'<=b && b<='9') {
354+ val*=10;
355+ val+=b-'0';
356+ } else {
357+ break;
358+ }
359+ }
360+ }
361+ return val*sign;
362+}
363+
364+char* lib_input(){
365+ // Allocate memory for strings with 63 characters
366+ char *str=calloc_memory((63+1)/4,-1);
367+ // Enable PS/2 keyboard
368+ if (!inPS2MODE()) {
369+ ps2mode();
370+ ps2init();
371+ }
372+ // Clear key buffer
373+ do ps2readkey();
374+ while(vkey!=0);
375+ // Get string as a line
376+ lineinput(str,63);
377+ check_break();
378+ return str;
379+}
380+
381+unsigned char lib_inkey(int key){
382+ int i;
383+ // Enable PS/2 keyboard
384+ if (!inPS2MODE()) {
385+ ps2mode();
386+ ps2init();
387+ }
388+ if (key) {
389+ return ps2keystatus[key&0xff];
390+ } else {
391+ for(i=0;i<256;i++){
392+ if (ps2keystatus[i]) return i;
393+ }
394+ return 0;
395+ }
396+}
397+
398+void lib_usepcg(int mode){
399+ // Modes; 0: stop PCG, 1: use PCG, 2: reset PCG and use it
400+ switch(mode){
401+ case 0:
402+ // Stop PCG
403+ stopPCG();
404+ break;
405+ case 2:
406+ // Reset PCG and use it
407+ if (g_pcg_font) {
408+ free_temp_str(g_pcg_font);
409+ g_pcg_font=0;
410+ }
411+ // Continue to case 1:
412+ case 1:
413+ default:
414+ // Use PCG
415+ if (g_pcg_font) {
416+ startPCG(g_pcg_font,0);
417+ } else {
418+ g_pcg_font=alloc_memory(256*8/4,ALLOC_PCG_BLOCK);
419+ startPCG(g_pcg_font,1);
420+ }
421+ break;
422+ }
423+}
424+
425+void lib_pcg(unsigned int ascii,unsigned int fontdata1,unsigned int fontdata2){
426+ unsigned int* pcg;
427+ // If USEPCG has not yet executed, do now.
428+ if (!g_pcg_font) lib_usepcg(1);
429+ pcg=(unsigned int*)g_pcg_font;
430+ // 0 <= ascii <= 0xff
431+ ascii&=0xff;
432+ // Update font data
433+ ascii<<=1;
434+ pcg[ascii]=(fontdata1>>24)|((fontdata1&0xff0000)>>8)|((fontdata1&0xff00)<<8)|(fontdata1<<24);
435+ pcg[ascii+1]=(fontdata2>>24)|((fontdata2&0xff0000)>>8)|((fontdata2&0xff00)<<8)|(fontdata2<<24);
436+}
437+
438+void lib_usegraphic(int mode){
439+ usegraphic(mode);
440+ // Move current point to (0,0)
441+ g_prev_x=g_prev_y=0;
442+}
443+void lib_wait(int period){
444+ int i;
445+ unsigned short dcount;
446+ for(i=0;i<period;i++){
447+ dcount=drawcount;
448+ while(dcount==drawcount){
449+ asm (WAIT);
450+ check_break();
451+ }
452+ }
453+}
454+
455+int lib_graphic(int v0,enum functions func){
456+ unsigned char b;
457+ int x1=g_libparams[1];
458+ int y1=g_libparams[2];
459+ int x2=g_libparams[3];
460+ int y2=g_libparams[4];
461+ // Disable if graphic area is not defined.
462+ if (!g_graphic_area) return;
463+ // If C is omitted in parameters, use current color.
464+ if (v0==-1) {
465+ v0=g_gcolor;
466+ }
467+ // If X1 or Y1 is 0x80000000, use the previous values.
468+ if (x1==0x80000000) x1=g_prev_x;
469+ if (y1==0x80000000) y1=g_prev_y;
470+ switch(func){
471+ case FUNC_POINT:// X1,Y1
472+ g_prev_x=x1;
473+ g_prev_y=y1;
474+ break;
475+ case FUNC_PSET:// X1,Y1[,C]
476+ g_pset(x1,y1,v0);
477+ g_prev_x=x1;
478+ g_prev_y=y1;
479+ break;
480+ case FUNC_LINE:// X1,Y1,X2,Y2[,C]
481+ if (y1==y2) g_hline(x1,x2,y1,v0);
482+ else g_gline(x1,y1,x2,y2,v0);
483+ g_prev_x=x2;
484+ g_prev_y=y2;
485+ break;
486+ case FUNC_BOXFILL:// X1,Y1,X2,Y2[,C]
487+ g_boxfill(x1,y1,x2,y2,v0);
488+ g_prev_x=x2;
489+ g_prev_y=y2;
490+ break;
491+ case FUNC_CIRCLE:// X1,Y1,R[,C]
492+ g_circle(x1,y1,x2,v0);
493+ g_prev_x=x1;
494+ g_prev_y=y1;
495+ break;
496+ case FUNC_CIRCLEFILL:// X1,Y1,R[,C]
497+ g_circlefill(x1,y1,x2,v0);
498+ g_prev_x=x1;
499+ g_prev_y=y1;
500+ break;
501+ case FUNC_GPRINT:// X1,Y1,C,BC,S$
502+ g_printstr(x1,y1,x2,y2,(unsigned char*)v0);
503+ // Move current X,Y according to the string
504+ while(b=((unsigned char*)v0)[0]){
505+ v0++;
506+ if (b==0x0d) {
507+ x1=0;
508+ y1+=8;
509+ } else {
510+ x1+=8;
511+ }
512+ }
513+ g_prev_x=x1;
514+ g_prev_y=y1;
515+ break;
516+ case FUNC_PUTBMP2:// X1,Y1,M,N,BMP(label)
517+ // Search CDATA
518+ // It starts from either 0x00000020,0x00000021,0x00000022, or 0x00000023.
519+ while((((unsigned int*)v0)[0]&0xfffffffc)!=0x00000020) v0+=4;
520+ // CDATA starts from next word.
521+ // MLB 3 bytes show skip byte(s).
522+ v0+=4+(((unsigned int*)v0)[0]&0x03);
523+ // Contunue to FUNC_PUTBMP.
524+ case FUNC_PUTBMP:// X1,Y1,M,N,BMP(pointer)
525+ g_putbmpmn(x1,y1,x2,y2,(const unsigned char*)v0);
526+ g_prev_x=x1;
527+ g_prev_y=y1;
528+ break;
529+ case FUNC_GCOLOR:// (X1,Y1)
530+ v0=g_color(x1,y1);
531+ break;
532+ default:
533+ break;
534+ }
535+ return v0;
536+}
537+
538+void lib_var_push(int a0, int a1, int* sp){
539+ // Note that sp[1] is used for string return address
540+ // sp[2] can be used to store flags
541+ // sp[3] etc can be used to store variable values
542+ int i,params;
543+ unsigned char varnum;
544+ unsigned int strflags=0;
545+ int stack=3;
546+ for(i=0;i<8;i++){
547+ // Prepare parameter
548+ switch(i){
549+ case 0:
550+ params=a0;
551+ break;
552+ case 4:
553+ params=a1;
554+ break;
555+ default:
556+ break;
557+ }
558+ // Get variable number
559+ varnum=params&0xff;
560+ params>>=8;
561+ if (varnum==0) break; // No more variable. End the loop.
562+ varnum--;
563+ sp[stack++]=g_var_mem[varnum];
564+ if (g_var_size[varnum] && g_var_mem[varnum]==(int)(&g_var_pointer[varnum])) {
565+ // strflags change using varnum
566+ strflags|=1<<i;
567+ // Copy to VAR_BLOCK
568+ move_to_perm_block(varnum);
569+ }
570+ // Clear variable
571+ g_var_mem[varnum]=0;
572+ }
573+ // Store string flags
574+ sp[2]=strflags;
575+}
576+
577+void lib_var_pop(int a0, int a1, int* sp){
578+ // Note that sp is 4 bytes larger than that in lib_var_push
579+ // sp[1] was used to store flags
580+ // sp[2] etc can be used to store variable values
581+ int i,params;
582+ unsigned char varnum;
583+ int stack=2;
584+ unsigned int strflags=sp[1];
585+ for(i=0;i<8;i++){
586+ // Prepare parameter
587+ switch(i){
588+ case 0:
589+ params=a0;
590+ break;
591+ case 4:
592+ params=a1;
593+ break;
594+ default:
595+ break;
596+ }
597+ // Get variable number
598+ varnum=params&0xff;
599+ params>>=8;
600+ if (varnum==0) break; // No more variable. End the loop.
601+ varnum--;
602+ g_var_mem[varnum]=sp[stack++];
603+ if (strflags&(1<<i)) {
604+ // Restore from VAR_BLOCK
605+ move_from_perm_block(varnum);
606+ }
607+ }
608+}
609+
610+
611+char* lib_sprintf(char* format, int data){
612+ char* str;
613+ int i;
614+ char temp[4];
615+ if (!format) format="%g";
616+ i=snprintf((char*)(&temp[0]),4,format,data)+1;
617+ str=alloc_memory((i+3)/4,-1);
618+ snprintf(str,i,format,data);
619+ return str;
620+}
621+
622+int lib_floatfuncs(int ia0,int iv0,enum functions a1){
623+ volatile float a0,v0;
624+ ((int*)(&a0))[0]=ia0;
625+ ((int*)(&v0))[0]=iv0;
626+ switch(a1){
627+ case FUNC_FLOAT:
628+ v0=(float)iv0;
629+ break;
630+ case FUNC_INT:
631+ return (int)v0;
632+ case FUNC_VALSHARP:
633+ v0=strtof((const char*)iv0,0);
634+ break;
635+ case FUNC_SIN:
636+ v0=sinf(v0);
637+ break;
638+ case FUNC_COS:
639+ v0=cosf(v0);
640+ break;
641+ case FUNC_TAN:
642+ v0=tanf(v0);
643+ break;
644+ case FUNC_ASIN:
645+ v0=asinf(v0);
646+ break;
647+ case FUNC_ACOS:
648+ v0=acosf(v0);
649+ break;
650+ case FUNC_ATAN:
651+ v0=atanf(v0);
652+ break;
653+ case FUNC_ATAN2:
654+ v0=atan2f(v0,a0);
655+ break;
656+ case FUNC_SINH:
657+ v0=sinhf(v0);
658+ break;
659+ case FUNC_COSH:
660+ v0=coshf(v0);
661+ break;
662+ case FUNC_TANH:
663+ v0=tanhf(v0);
664+ break;
665+ case FUNC_EXP:
666+ v0=expf(v0);
667+ break;
668+ case FUNC_LOG:
669+ v0=logf(v0);
670+ break;
671+ case FUNC_LOG10:
672+ v0=log10f(v0);
673+ break;
674+ case FUNC_POW:
675+ v0=powf(v0,a0);
676+ break;
677+ case FUNC_SQRT:
678+ v0=sqrtf(v0);
679+ break;
680+ case FUNC_CEIL:
681+ v0=ceilf(v0);
682+ break;
683+ case FUNC_FLOOR:
684+ v0=floorf(v0);
685+ break;
686+ case FUNC_FABS:
687+ v0=fabsf(v0);
688+ break;
689+ case FUNC_MODF:
690+ v0=modff(v0,(void*)&a0);
691+ break;
692+ case FUNC_FMOD:
693+ v0=fmodf(v0,a0);
694+ break;
695+ default:
696+ err_unknown();
697+ break;
698+ }
699+ return ((int*)(&v0))[0];
700+};
701+
702+int* lib_dim(int varnum, int argsnum, int* sp){
703+ int i,j;
704+ static int* heap;
705+ // Calculate total length.
706+ int len=0; // Total length
707+ int size=1; // Size of current block
708+ for(i=1;i<=argsnum;i++){
709+ size*=sp[i]+1;
710+ len+=size;
711+ }
712+ // Allocate memory
713+ heap=calloc_memory(len,varnum);
714+ // Construct pointers
715+ len=0;
716+ size=1;
717+ for(i=1;i<argsnum;i++){
718+ size*=sp[i]+1;
719+ for(j=0;j<size;j++){
720+ heap[len+j]=(int)&heap[len+size+(sp[i+1]+1)*j];
721+ }
722+ len+=size;
723+ }
724+ return heap;
725+};
726+
727+int lib_file_textlen(FSFILE* fhandle){
728+ char buff[128];
729+ int i,textlen,len,seek;
730+ seek=FSftell(fhandle);
731+ len=FSfread(&buff[0],1,128,fhandle);
732+ textlen=0;
733+ for(i=0;i<len-1;i++){ // Read 127 bytes for supporting CRLF
734+ if (buff[i]==0x0d) {
735+ if (i<len && buff[i+1]==0x0a) i++;
736+ break;
737+ } else if (buff[i]==0x0a) {
738+ break;
739+ }
740+ if (i==len-2) {
741+ // reached the end of buffer. Read next 127 bytes
742+ textlen+=127;
743+ buff[0]=buff[127];
744+ len=FSfread(&buff[1],1,127,fhandle);
745+ // Continue with i=0
746+ i=-1;
747+ }
748+ }
749+ // The last return code must be included to caluclate total length.
750+ textlen+=i+1;
751+ // Return to original position
752+ FSfseek(fhandle,seek,SEEK_SET);
753+ return textlen;
754+}
755+
756+int lib_file(enum functions func, int a0, int a1, int v0){
757+ static FSFILE* s_fhandle[2]={0,0};
758+ static char activefhandle=0;
759+ static int numinline=0;
760+ FSFILE* fhandle=0;
761+ int i;
762+ int buff[1];
763+ char* str;
764+ if (activefhandle) fhandle=s_fhandle[activefhandle-1];
765+ switch(func){
766+ case FUNC_FINIT:
767+ // This function is not BASIC statement/function but used from
768+ // running routine.
769+ for(i=0;i<2;i++){
770+ if (s_fhandle[i]) FSfclose(s_fhandle[i]);
771+ s_fhandle[i]=0;
772+ }
773+ activefhandle=0;
774+ numinline=0;
775+ break;
776+ case FUNC_FOPEN: // Return 0 when called as a function.
777+ case FUNC_FOPENST: // Stop with error when called as a statement.
778+ activefhandle=0;
779+ // Check if file handle is free to use, first.
780+ switch(v0){
781+ case 0:
782+ // File handle was not designated
783+ // Force handle=1 and continue to following cases.
784+ v0=1;
785+ case 1:
786+ case 2:
787+ // File handle was designated
788+ // Check if not used yet.
789+ if (s_fhandle[v0-1]) {
790+ // This file handle has been occupied.
791+ err_file();
792+ return 0;
793+ }
794+ // OK. This file handle can be asigned for new file opened.
795+ break;
796+ default:
797+ err_invalid_param();
798+ return 0;
799+ }
800+ // Open a file
801+ fhandle=FSfopen ((const char*) a0, (const char*) a1);
802+ if (!fhandle) {
803+ if (func==FUNC_FOPENST) err_file();
804+ return 0;
805+ }
806+ // The file is succesfully opened. Asign file handle.
807+ s_fhandle[v0-1]=fhandle;
808+ activefhandle=v0;
809+ return v0;
810+ case FUNC_FILE:
811+ switch(v0){
812+ case 1:
813+ case 2:
814+ if (s_fhandle[v0]) {
815+ activefhandle=v0;
816+ break;
817+ }
818+ default:
819+ err_invalid_param();
820+ }
821+ break;
822+ case FUNC_FCLOSE:
823+ switch(v0){
824+ case 0:
825+ break;
826+ case 1:
827+ case 2:
828+ if (s_fhandle[v0-1]) activefhandle=v0;
829+ if (activefhandle) fhandle=s_fhandle[activefhandle-1];
830+ break;
831+ default:
832+ err_invalid_param();
833+ }
834+ if (fhandle) {
835+ FSfclose(fhandle);
836+ s_fhandle[activefhandle-1]=0;
837+ }
838+ activefhandle=0;
839+ break;
840+ case FUNC_FINPUT:
841+ if (fhandle) {
842+ // Determine text length if called without parameter
843+ if (v0==0) v0=lib_file_textlen(fhandle);
844+ // Allocate temporary area for string
845+ str=alloc_memory((v0+1+3)/4,-1);
846+ // Read from SD card
847+ v0=FSfread(str,1,v0,fhandle);
848+ // Null string at the end.
849+ str[v0]=0;
850+ return (int)str;
851+ } else {
852+ err_file();
853+ return (int)"";
854+ }
855+ case FUNC_FPRINTSTR:
856+ // Like lib_printstr()
857+ for(i=0;((char*)v0)[i];i++);
858+ if (fhandle) {
859+ if (!FSfwrite((char*)v0,1,i,fhandle)) err_file();
860+ } else err_file();
861+ numinline+=i;
862+ break;
863+ case FUNC_FSTRING:
864+ // Like lib_string()
865+ switch(v0){
866+ case 0:
867+ // CR
868+ lib_file(FUNC_FPRINTSTR,a0,a1,(int)"\r\n");
869+ numinline=0;
870+ break;
871+ case 1:
872+ // ,
873+ i=rem10_32(numinline);
874+ lib_file(FUNC_FPRINTSTR,a0,a1,(int)(" "+i));
875+ break;
876+ default:
877+ break;
878+ }
879+ break;
880+ case FUNC_FGET:
881+ if (fhandle) return FSfread((void*)a0,1,v0,fhandle);
882+ err_file();
883+ break;
884+ case FUNC_FPUT:
885+ if (fhandle) return FSfwrite((void*)a0,1,v0,fhandle);
886+ err_file();
887+ break;
888+ case FUNC_FGETC:
889+ if (fhandle) {
890+ // Note: Little endian.
891+ if (FSfread((void*)&buff[0],1,1,fhandle)) return buff[0]&0xff;
892+ else return -1;
893+ }
894+ err_file();
895+ break;
896+ case FUNC_FPUTC:
897+ if (fhandle) {
898+ // Note: Little endian.
899+ buff[0]=v0;
900+ return FSfwrite((void*)&buff[0],1,1,fhandle);
901+ }
902+ err_file();
903+ break;
904+ case FUNC_FSEEK:
905+ if (fhandle) return FSfseek(fhandle,v0,SEEK_SET);
906+ err_file();
907+ break;
908+ case FUNC_FTELL:
909+ if (fhandle) return FSftell(fhandle);
910+ err_file();
911+ break;
912+ case FUNC_FLEN:
913+ if (fhandle) return fhandle->size;
914+ err_file();
915+ break;
916+ case FUNC_FEOF:
917+ if (fhandle) return (fhandle->size<=FSftell(fhandle)) ? 1:0;
918+ err_file();
919+ break;
920+ case FUNC_FREMOVE:
921+ return FSremove((const char *)v0);
922+ default:
923+ err_unknown();
924+ }
925+ return v0;
926+}
927+
928+int _call_library(int a0,int a1,int a2,enum libs a3);
929+
930+void call_library(void){
931+ // Store s6 in g_s6
932+ asm volatile("la $a2,%0"::"i"(&g_s6));
933+ asm volatile("sw $s6,0($a2)");
934+ // Copy $v0 to $a2 as 3rd argument of function
935+ asm volatile("addu $a2,$v0,$zero");
936+ // Store sp in g_libparams
937+ asm volatile("la $v0,%0"::"i"(&g_libparams));
938+ asm volatile("sw $sp,0($v0)");
939+ // Jump to main routine
940+ asm volatile("j _call_library");
941+}
942+
943+int _call_library(int a0,int a1,int v0,enum libs a3){
944+ // usage: call_lib_code(LIB_XXXX);
945+ // Above code takes 2 words.
946+ check_break();
947+ switch(a3 & LIB_MASK){
948+ case LIB_FLOAT:
949+ return lib_float(a0,v0,(enum operator)(a3 & OP_MASK)); // see operator.c
950+ case LIB_FLOATFUNCS:
951+ return lib_floatfuncs(a0,v0,(enum functions)(a3 & FUNC_MASK));
952+ case LIB_STRNCMP:
953+ return strncmp((char*)g_libparams[1],(char*)g_libparams[2],v0);
954+ case LIB_MIDSTR:
955+ return (int)lib_midstr(a1,v0,a0);
956+ case LIB_RND:
957+ return (int)lib_rnd();
958+ case LIB_DEC:
959+ return (int)lib_dec(v0);
960+ case LIB_HEX:
961+ return (int)lib_hex(v0,a0);
962+ case LIB_CHR:
963+ return (int)lib_chr(v0);
964+ case LIB_VAL:
965+ return lib_val((char*)v0);
966+ case LIB_LETSTR:
967+ lib_let_str((char*)v0,a0);
968+ return;
969+ case LIB_CONNECT_STRING:
970+ return (int)lib_connect_string((char*)a0, (char*)v0);
971+ case LIB_STRING:
972+ lib_string(v0);
973+ return v0;
974+ case LIB_PRINTSTR:
975+ printstr((char*)v0);
976+ return v0;
977+ case LIB_GRAPHIC:
978+ return lib_graphic(v0, (enum functions)(a3 & FUNC_MASK));
979+ case LIB_SPRINTF:
980+ return (int)lib_sprintf((char*)v0,a0);
981+ case LIB_VAR_PUSH:
982+ lib_var_push(a0,a1,g_libparams);
983+ return v0;
984+ case LIB_VAR_POP:
985+ lib_var_pop(a0,a1,g_libparams);
986+ return v0;
987+ case LIB_SCROLL:
988+ scroll(g_libparams[1],v0);
989+ return v0;
990+ case LIB_FILE:
991+ return lib_file((enum functions)(a3 & FUNC_MASK),g_libparams[1],g_libparams[2],v0);
992+ case LIB_KEYS:
993+ return lib_keys(v0);
994+ case LIB_INKEY:
995+ return (int)lib_inkey(v0);
996+ case LIB_CURSOR:
997+ setcursor(g_libparams[1],v0,cursorcolor);
998+ return v0;
999+ case LIB_SOUND:
1000+ set_sound((unsigned long*)v0,a0);
1001+ return v0;
1002+ case LIB_MUSICFUNC:
1003+ return musicRemaining(a0);
1004+ case LIB_MUSIC:
1005+ set_music((char*)v0,a0);
1006+ return v0;
1007+ case LIB_PLAYWAVE:
1008+ play_wave((char*)g_libparams[1],v0);
1009+ return v0;
1010+ case LIB_PLAYWAVEFUNC:
1011+ return waveRemaining(v0);
1012+ case LIB_SETDRAWCOUNT:
1013+ drawcount=(v0&0x0000FFFF);
1014+ return v0;
1015+ case LIB_DRAWCOUNT:
1016+ return drawcount;
1017+ case LIB_SYSTEM:
1018+ return lib_system(a0, a1 ,v0, a3, g_gcolor, g_prev_x, g_prev_y);
1019+ case LIB_RESTORE:
1020+ return lib_read(0,v0);
1021+ case LIB_RESTORE2:
1022+ return lib_read(1,v0);
1023+ case LIB_READ:
1024+ return lib_read(0,0);
1025+ case LIB_CREAD:
1026+ return lib_read(1,0);
1027+ case LIB_LABEL:
1028+ return (int)lib_label(v0);
1029+ case LIB_INPUT:
1030+ return (int)lib_input();
1031+ case LIB_USEGRAPHIC:
1032+ lib_usegraphic(v0);
1033+ return v0;
1034+ case LIB_USEPCG:
1035+ lib_usepcg(v0);
1036+ return v0;
1037+ case LIB_PCG:
1038+ lib_pcg(g_libparams[1],g_libparams[2],v0);
1039+ return v0;
1040+ case LIB_BGCOLOR: // BGCOLOR R,G,B
1041+ set_bgcolor(v0,g_libparams[1],g_libparams[2]); //set_bgcolor(b,r,g);
1042+ return v0;
1043+ case LIB_PALETTE: // PALETTE N,R,G,B
1044+ set_palette(g_libparams[1],v0,g_libparams[2],g_libparams[3]); // set_palette(n,b,r,g);
1045+ return v0;
1046+ case LIB_GPALETTE:// GPALETTE N,R,G,B
1047+ if (g_graphic_area) g_set_palette(g_libparams[1],v0,g_libparams[2],g_libparams[3]); // g_set_palette(n,b,r,g);
1048+ return v0;
1049+ case LIB_CLS:
1050+ clearscreen();
1051+ return v0;
1052+ case LIB_GCLS:
1053+ if (g_graphic_area) g_clearscreen();
1054+ g_prev_x=g_prev_y=0;
1055+ return v0;
1056+ case LIB_WIDTH:
1057+ videowidth(v0);
1058+ return v0;
1059+ case LIB_COLOR:
1060+ setcursorcolor(v0);
1061+ return v0;
1062+ case LIB_GCOLOR:
1063+ g_gcolor=v0;
1064+ return v0;
1065+ case LIB_WAIT:
1066+ lib_wait(v0);
1067+ return v0;
1068+ case LIB_CLEAR:
1069+ lib_clear();
1070+ return v0;
1071+ case LIB_DIM:
1072+ return (int)lib_dim(a0,a1,(int*)v0);
1073+#ifdef __DEBUG
1074+ case LIB_DEBUG:
1075+ asm volatile("nop");
1076+ return v0;
1077+#endif
1078+ case LIB_DIV0:
1079+ err_div_zero();
1080+ return v0;
1081+ default:
1082+ err_unknown();
1083+ return v0;
1084+ }
1085+}
\ No newline at end of file
--- mips/branches/zoeaobjective/memory.c (nonexistent)
+++ mips/branches/zoeaobjective/memory.c (revision 271)
@@ -0,0 +1,184 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by Katsumi.
4+ http://hp.vector.co.jp/authors/VA016157/
5+ kmorimatsu@users.sourceforge.jp
6+*/
7+
8+#include "compiler.h"
9+
10+/*
11+ ALLOC_VAR_NUM: # of variables used for allocation of memory (string/dimension).
12+ 0 is for A, 1 is for B, ... , and 25 is for Z.
13+ This number also includes temporary area used for string construction etc.
14+ Temporary area is cleared every line of BASIC code in alloc_memory().
15+ ALLOC_BLOCK_NUM: # of blocks that can be used for memory allocation.
16+ This # also includes the ones for ALLOC_VAR_NUM.
17+ After ALLOC_VAR_NUM area, dedicated memory area and permanent area follows.
18+ Currently, only PCG is used for permanent pourpose.
19+ 10 permanant blocks can be used.
20+ Therefore, ALLOC_VAR_NUM+11 == ALLOC_BLOCK_NUM
21+ ALLOC_PERM_BLOCK: Start # of permanent blocks.
22+ The blocks after this number is permanently stored.
23+ Therefore, it must be released when it's not used any more.
24+*/
25+
26+void set_free_area(void* begin, void* end){
27+ int i;
28+ for(i=0;i<ALLOC_BLOCK_NUM;i++){
29+ g_var_size[i]=0;
30+ }
31+ g_heap_mem=(int*)begin;
32+ g_max_mem=(int)((end-begin)/4);
33+}
34+
35+void* calloc_memory(int size, int var_num){
36+ int i;
37+ void* ret;
38+ // Allocate memory
39+ ret=alloc_memory(size,var_num);
40+ // Fill zero in allocated memory
41+ for(i=0;i<size;i++){
42+ ((int*)ret)[i]=0;
43+ }
44+ // return pointer to allocated memory
45+ return ret;
46+}
47+void* alloc_memory(int size, int var_num){
48+ // Remove temporary blocks once a line.
49+ asm volatile("nop");
50+ asm volatile("bltz $s6,_alloc_memory_main"); // Skip if $s6<0
51+ // Following code will be activated after setting $s6 register
52+ // every line and after label statement.
53+ asm volatile("lui $v0,0x8000");
54+ asm volatile("or $s6,$v0,$s6"); // $s6=0x80000000|$s6;
55+ // Remove all temporary blocks
56+ // Note that g_var_size is short integer.
57+ // Note that ALLOC_VAR_NUM is used here (but not ALLOC_BLOC_NUM)
58+ // for(i=26;i<ALLOC_VAR_NUM;i++)g_var_size[i]=0;
59+ asm volatile("addiu $v0,$zero,%0"::"n"((ALLOC_VAR_NUM-26)/2)); // $v0=(ALLOC_VAR_NUM-26)/2
60+ asm volatile("la $v1,%0"::"i"(&g_var_size[0])); // $v1=g_var_size
61+ asm volatile("loop:");
62+ asm volatile("sw $zero,(26*2)($v1)"); // $v1[26]=0, $v1[27]=0
63+ asm volatile("addiu $v0,$v0,-1"); // $v0--
64+ asm volatile("addiu $v1,$v1,4"); // $v1+=2
65+ asm volatile("bne $v0,$zero,loop"); // loop if 0<$v0
66+ asm volatile("b _alloc_memory_main");
67+}
68+void* _alloc_memory_main(int size, int var_num){
69+ int i,j,candidate;
70+ // Assign temp var number
71+ if (var_num<0) {
72+ // Use ALLOC_VAR_NUM here but not ALLOC_BLOCK_NUM
73+ for(i=26;i<ALLOC_VAR_NUM;i++){
74+ if (g_var_size[i]==0) {
75+ var_num=i;
76+ break;
77+ }
78+ }
79+ if (var_num<0) {
80+ err_str_complex();
81+ return 0;
82+ }
83+ }
84+ // Clear var to be assigned.
85+ g_var_size[var_num]=0;
86+ g_var_pointer[var_num]=0;
87+ while(1){
88+ // Try the block after last block
89+ candidate=0;
90+ for(i=0;i<ALLOC_BLOCK_NUM;i++){
91+ if (g_var_size[i]==0) continue;
92+ if (candidate<=g_var_pointer[i]) {
93+ candidate=g_var_pointer[i]+g_var_size[i];
94+ }
95+ }
96+ if (candidate+size<=g_max_mem) break;
97+ // Check between blocks
98+ // Note that there is at least one block with zero pointer and zero size (see above).
99+ for(i=0;i<ALLOC_BLOCK_NUM;i++){
100+ // Candidate is after this block.
101+ candidate=g_var_pointer[i]+g_var_size[i];
102+ // Check if there is an overlap.
103+ for(j=0;j<ALLOC_BLOCK_NUM;j++){
104+ if (g_var_size[j]==0) continue;
105+ if (candidate+size<=g_var_pointer[j]) continue;
106+ if (g_var_pointer[j]+g_var_size[j]<=candidate) continue;
107+ // This block overlaps with the candidate
108+ candidate=-1;
109+ break;
110+ }
111+ if (0<=candidate && candidate+size<=g_max_mem) {
112+ // Available block found
113+ break;
114+ } else {
115+ candidate=-1;
116+ }
117+ }
118+ if (0<=candidate) break;
119+ // New memory block cannot be allocated.
120+ err_no_mem();
121+ return 0;
122+ }
123+ // Available block found.
124+ g_var_pointer[var_num]=candidate;
125+ g_var_size[var_num]=size;
126+ g_var_mem[var_num]=(int)(&(g_heap_mem[candidate]));
127+ return (void*)g_var_mem[var_num];
128+}
129+
130+void free_temp_str(char* str){
131+ int i,pointer;
132+ if (!str) return;
133+ pointer=(int)str-(int)g_heap_mem;
134+ pointer>>=2;
135+ for(i=0;i<ALLOC_BLOCK_NUM;i++){
136+ if (g_var_pointer[i]==pointer) {
137+ g_var_size[i]=0;
138+ break;
139+ }
140+ }
141+}
142+
143+void move_to_perm_block(int var_num){
144+ int i;
145+ // Find available permanent block
146+ for (i=ALLOC_PERM_BLOCK;i<ALLOC_BLOCK_NUM;i++){
147+ if (g_var_size[i]==0) break;
148+ }
149+ if (ALLOC_BLOCK_NUM<=i) err_no_block(); // Not found
150+ // Available block found.
151+ // Copy value from variable.
152+ g_var_size[i]=g_var_size[var_num];
153+ g_var_pointer[i]=g_var_pointer[var_num];
154+ g_var_mem[i]=g_var_mem[var_num];
155+ // Clear variable
156+ g_var_size[var_num]=0;
157+ g_var_mem[var_num]=0;
158+}
159+
160+void move_from_perm_block(int var_num){
161+ int i,pointer;
162+ pointer=(int)g_var_mem[var_num]-(int)g_heap_mem;
163+ pointer>>=2;
164+ // Find stored block
165+ for (i=ALLOC_PERM_BLOCK;i<ALLOC_BLOCK_NUM;i++){
166+ if (0<g_var_size[i] && g_var_pointer[i]==pointer) break;
167+ }
168+ if (ALLOC_BLOCK_NUM<=i) err_unknown(); // Not found
169+ // Stored block found.
170+ // Replace pointer
171+ g_var_size[var_num]=g_var_size[i];
172+ g_var_pointer[var_num]=g_var_pointer[i];
173+ // Clear block
174+ g_var_size[i]=0;
175+}
176+
177+int get_permanent_var_num(){
178+ int i;
179+ for (i=ALLOC_PERM_BLOCK;i<ALLOC_BLOCK_NUM;i++) {
180+ if (g_var_size[i]==0) return i;
181+ }
182+ err_no_block();
183+ return 0;
184+}
--- mips/branches/zoeaobjective/reservednames.js (nonexistent)
+++ mips/branches/zoeaobjective/reservednames.js (revision 271)
@@ -0,0 +1,175 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by Katsumi.
4+ http://hp.vector.co.jp/authors/VA016157/
5+ kmorimatsu@users.sourceforge.jp
6+*/
7+
8+/*
9+ This script is to make lines of reserved words for long var names.
10+*/
11+
12+function name2int(name){
13+ var g_source=name+'$';
14+ var g_srcpos=0;
15+ var prevpos=0;
16+ var i=0;
17+ var b1=g_source.charCodeAt(0);
18+ do {
19+ // First character must be A-Z
20+ // From second, A-Z and 0-9 can be used.
21+ i*=36;
22+ if ('0'.charCodeAt(0)<=b1 && b1<='9'.charCodeAt(0)) {
23+ i+=b1-'0'.charCodeAt(0);
24+ } else if (g_srcpos==prevpos) {
25+ // First character must be A-Z.
26+ // Subtract 9, resulting 1-26 but not 10-35.
27+ // This subtraction is required to maintain
28+ // final number being <0x80000000.
29+ i+=b1-'A'.charCodeAt(0)+1;
30+ } else {
31+ i+=b1-'A'.charCodeAt(0)+10;
32+ }
33+ g_srcpos++;
34+ b1=g_source.charCodeAt(g_srcpos);
35+ } while ('0'.charCodeAt(0)<= b1 && b1<='9'.charCodeAt(0) || 'A'.charCodeAt(0)<=b1 && b1<='Z'.charCodeAt(0));
36+ return i+65536;
37+}
38+
39+var namearray=[
40+ 'ABS',
41+ 'ACOS',
42+ 'ARGS',
43+ 'ASC',
44+ 'ASIN',
45+ 'ATAN',
46+ 'ATAN2',
47+ 'BREAK',
48+ 'CDATA',
49+ 'CEIL',
50+ 'CHR',
51+ 'CIRCLE',
52+ 'CLEAR',
53+ 'CLS',
54+ 'COLOR',
55+ 'COS',
56+ 'COSH',
57+ 'CREAD',
58+ 'CURSOR',
59+ 'DATA',
60+ 'DEC',
61+ 'DIM',
62+ 'DO',
63+ 'ELSE',
64+ 'ELSEIF',
65+ 'END',
66+ 'ENDIF',
67+ 'EXEC',
68+ 'EXP',
69+ 'FABS',
70+ 'FCLOSE',
71+ 'FEOF',
72+ 'FGET',
73+ 'FGETC',
74+ 'FILE',
75+ 'FINPUT',
76+ 'FLEN',
77+ 'FLOAT',
78+ 'FLOOR',
79+ 'FMOD',
80+ 'FOPEN',
81+ 'FOR',
82+ 'FPRINT',
83+ 'FPUT',
84+ 'FPUTC',
85+ 'FSEEK',
86+ 'GCLS',
87+ 'GCOLOR',
88+ 'GOSUB',
89+ 'GOTO',
90+ 'GPRINT',
91+ 'HEX',
92+ 'IF',
93+ 'INKEY',
94+ 'INPUT',
95+ 'INT',
96+ 'KEYS',
97+ 'LABEL',
98+ 'LEN',
99+ 'LET',
100+ 'LINE',
101+ 'LOG',
102+ 'LOG10',
103+ 'LOOP',
104+ 'MODF',
105+ 'MUSIC',
106+ 'NEXT',
107+ 'NOT',
108+ 'PCG',
109+ 'PEEK',
110+ 'PI',
111+ 'POINT',
112+ 'POKE',
113+ 'POW',
114+ 'PRINT',
115+ 'PSET',
116+ 'PUTBMP',
117+ 'READ',
118+ 'REM',
119+ 'RETURN',
120+ 'RND',
121+ 'SCROLL',
122+ 'SGN',
123+ 'SIN',
124+ 'SINH',
125+ 'SOUND',
126+ 'SQRT',
127+ 'SYSTEM',
128+ 'TAN',
129+ 'TANH',
130+ 'TVRAM',
131+ 'UNTIL',
132+ 'USEPCG',
133+ 'USEVAR',
134+ 'VAL',
135+ 'VAR',
136+ 'WAIT',
137+ 'WEND',
138+ 'WHILE',
139+ 'WIDTH',
140+ // For megalopa
141+ '// For Megalopa',
142+ 'OUT',
143+ 'OUT8H',
144+ 'OUT8L',
145+ 'OUT16',
146+ 'IN',
147+ 'IN8H',
148+ 'IN8L',
149+ 'IN16',
150+ 'ANALOG',
151+ 'PWM',
152+ 'SERIAL',
153+ 'SPI',
154+ 'SPIOUT',
155+ 'SPIIN',
156+];
157+var result='';
158+for(key in namearray){
159+ var nameint='0000'+name2int(namearray[key]).toString(16);
160+ nameint=nameint.substr(nameint.length-8);
161+ if (namearray[key].substr(0,2)=='//') {
162+ // This is a comment
163+ result+=namearray[key]+"\r\n";
164+ } else {
165+ result+="\t0x"+nameint+", /*"+namearray[key]+"*/\r\n";
166+ }
167+}
168+
169+var fso = new ActiveXObject("Scripting.FileSystemObject");
170+var file = fso.CreateTextFile("result.txt");
171+file.Write(result);
172+file.Close();
173+
174+WScript.Echo('Done!');
175+
--- mips/branches/zoeaobjective/run.c (nonexistent)
+++ mips/branches/zoeaobjective/run.c (revision 271)
@@ -0,0 +1,152 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by K.Tanaka & Katsumi
4+ http://www.ze.em-net.ne.jp/~kenken/index.html
5+ http://hp.vector.co.jp/authors/VA016157/
6+*/
7+
8+#include <xc.h>
9+#include "api.h"
10+#include "compiler.h"
11+#include "editor.h"
12+#include "main.h"
13+
14+char* printdec(int num){
15+ char str[11];
16+ int i;
17+ if (num<0) {
18+ printchar('-');
19+ num=0-num;
20+ }
21+ for(i=10;0<i;i--){
22+ if (num==0 && i<10) break;
23+ str[i]='0'+rem10_32(num);
24+ num=div10_32(num);
25+ }
26+ for(i++;i<11;i++) {
27+ printchar(str[i]);
28+ }
29+}
30+
31+int runbasic(char *appname,int test){
32+// BASICソースのコンパイルと実行
33+// appname 実行するBASICソースファイル
34+// test 0:コンパイルと実行、0以外:コンパイルのみで終了
35+//
36+// 戻り値
37+//  0:正常終了
38+//  -1:ファイルエラー
39+//  -2:リンクエラー
40+//  1以上:コンパイルエラーの発生行(行番号ではなくファイル上の何行目か)
41+ int i;
42+ char* buff;
43+ char* err;
44+
45+ // Set grobal pointer
46+ g_gp=get_gp();
47+ // Set source positions
48+ buff=(char*)&(RAM[RAMSIZE-512]);
49+ g_source=(char*)(&buff[0]);
50+ g_srcpos=0;
51+ // Set object positions
52+ g_object=(int*)(&RAM[0]);
53+ g_objpos=0;
54+ g_objmax=g_object+(RAMSIZE-512)/4; // Buffer area excluded.
55+ // Clear object area
56+ for(i=0;i<RAMSIZE/4;i++) g_object[i]=0x00000000;
57+ // Initialize SD card file system
58+ err=init_file(buff,appname);
59+ if (err) {
60+ setcursorcolor(COLOR_ERRORTEXT);
61+ printstr("Can't Open ");
62+ printstr(appname);
63+ printchar('\n');
64+ return -1;
65+ }
66+
67+ // Initialize parameters
68+ g_pcg_font=0;
69+ g_use_graphic=0;
70+ g_graphic_area=0;
71+ clearscreen();
72+ setcursor(0,0,7);
73+ g_long_name_var_num=0;
74+ cmpdata_init();
75+
76+ // Initialize music system
77+ init_music();
78+
79+ printstr("BASIC "BASVER"\n");
80+ wait60thsec(15);
81+
82+ printstr("Compiling...");
83+
84+ // Compile the file
85+ err=compile_file();
86+ close_file();
87+ if (err) {
88+ // Compile error
89+ printstr(err);
90+ printstr("\nAround: '");
91+ for(i=0;i<5;i++){
92+ printchar(g_source[g_srcpos-2+i]);
93+ }
94+ printstr("' in line ");
95+ printdec(g_line);
96+ printstr("\n");
97+ for(i=g_srcpos;0x20<=g_source[i];i++);
98+ g_source[i]=0x00;
99+ for(i=g_srcpos;0x20<=g_source[i];i--);
100+ printstr(g_source+i);
101+ return g_fileline;
102+ }
103+
104+ // Link
105+ err=link();
106+ if (err) {
107+ // Link error
108+ printstr(err);
109+ printstr(resolve_label(g_label));
110+ return -2;
111+ }
112+
113+ // All done
114+ printstr("done\n");
115+ if(test) return 0; //コンパイルのみの場合
116+ wait60thsec(15);
117+
118+ // Initialize the other parameters
119+ // Random seed
120+ g_rnd_seed=0x92D68CA2; //2463534242
121+ // Clear variables
122+ for(i=0;i<ALLOC_BLOCK_NUM;i++){
123+ g_var_mem[i]=0;
124+ g_var_size[i]=0;
125+ }
126+ // Clear key input buffer
127+ for(i=0;i<256;i++){
128+ ps2keystatus[i]=0;
129+ }
130+ // Reset data/read.
131+ reset_dataread();
132+ // Initialize file system
133+ lib_file(FUNC_FINIT,0,0,0);
134+
135+ // Assign memory
136+ set_free_area((void*)(g_object+g_objpos),(void*)(&RAM[RAMSIZE]));
137+
138+ // Warm up environment
139+ pre_run();
140+
141+ // Execute program
142+ // Start program from the beginning of RAM.
143+ // Work area (used for A-Z values) is next to the object code area.
144+ start_program((void*)(&(RAM[0])),(void*)(&g_var_mem[0]));
145+ printstr("\nOK\n");
146+
147+ // Cool down environment
148+ post_run();
149+ lib_file(FUNC_FINIT,0,0,0);
150+
151+ return 0;
152+}
--- mips/branches/zoeaobjective/statement.c (nonexistent)
+++ mips/branches/zoeaobjective/statement.c (revision 271)
@@ -0,0 +1,1637 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by Katsumi.
4+ http://hp.vector.co.jp/authors/VA016157/
5+ kmorimatsu@users.sourceforge.jp
6+*/
7+
8+#include "api.h"
9+#include "compiler.h"
10+
11+char* rem_statement(){
12+ if (g_source[g_srcpos-4]<0x20) {
13+ // This line contains only "REM" statement
14+ // Delete $s6-setting command if exists.
15+ if ((g_object[g_objpos-1]&0xffff0000)==0x34160000) g_objpos--;
16+ }
17+ while(0x20<=g_source[g_srcpos]){
18+ g_srcpos++;
19+ }
20+ return 0;
21+}
22+
23+char* sound_statement(){
24+ char *err;
25+ err=get_label();
26+ if (err) return err;
27+ if (g_label) {
28+ // Label/number is constant.
29+ // Linker will change following codes later.
30+ // Note that 0x0814xxxx and 0x0815xxxx are specific codes for these.
31+ check_obj_space(2);
32+ g_object[g_objpos++]=0x08140000|((g_label>>16)&0x0000FFFF); // lui v0,xxxx
33+ g_object[g_objpos++]=0x08150000|(g_label&0x0000FFFF); // ori v0,v0,xxxx
34+ } else {
35+ // Label/number will be dynamically set when executing code.
36+ err=get_value();
37+ if (err) return err;
38+ call_lib_code(LIB_LABEL);
39+ }
40+ // 2nd param is optional
41+ next_position();
42+ if (g_source[g_srcpos]==',') {
43+ g_srcpos++;
44+ check_obj_space(2);
45+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
46+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
47+ err=get_value();
48+ if (err) return err;
49+ check_obj_space(3);
50+ g_object[g_objpos++]=0x00402021; // addu a0,v0,zero
51+ g_object[g_objpos++]=0x8FA20004; // lw v0,4(sp)
52+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
53+ } else {
54+ // Set 3 if omitted
55+ check_obj_space(1);
56+ g_object[g_objpos++]=0x24040003; // addiu a0,zero,xx
57+ }
58+ call_lib_code(LIB_SOUND);
59+ return 0;
60+}
61+char* music_statement(){
62+ char *err;
63+ err=get_string();
64+ if (err) return err;
65+ // 2nd param is optional
66+ next_position();
67+ if (g_source[g_srcpos]==',') {
68+ g_srcpos++;
69+ check_obj_space(2);
70+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
71+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
72+ err=get_value();
73+ if (err) return err;
74+ check_obj_space(3);
75+ g_object[g_objpos++]=0x00402021; // addu a0,v0,zero
76+ g_object[g_objpos++]=0x8FA20004; // lw v0,4(sp)
77+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
78+ } else {
79+ // Set 3 if omitted
80+ check_obj_space(1);
81+ g_object[g_objpos++]=0x24040003; // addiu a0,zero,xx
82+ }
83+ call_lib_code(LIB_MUSIC);
84+ return 0;
85+}
86+
87+char* exec_statement(){
88+ char *err;
89+ char b1;
90+ int i,prevpos;
91+ b1=g_source[g_srcpos];
92+ while('0'<=b1 && b1<='9' || b1=='-' || b1=='$'){
93+ prevpos=g_objpos;
94+ g_valueisconst=1;
95+ err=get_simple_value();
96+ if (!g_valueisconst) err=ERR_SYNTAX;
97+ if (err) return err;
98+ check_obj_space(1);
99+ g_objpos=prevpos;
100+ g_object[g_objpos++]=g_intconst;
101+ next_position();
102+ b1=g_source[g_srcpos];
103+ if (b1!=',') break;
104+ g_srcpos++;
105+ next_position();
106+ b1=g_source[g_srcpos];
107+ if (b1==0x0d || b1==0x0a) {
108+ // Multiline DATA/EXEC statement
109+ g_line++;
110+ g_fileline++;
111+ if (b1==0x0D && g_source[g_srcpos+1]==0x0A) g_srcpos++;
112+ g_srcpos++;
113+ // Maintain at least 256 characters in cache.
114+ if (256<=g_srcpos) read_file(256);
115+ next_position();
116+ b1=g_source[g_srcpos];
117+ }
118+ }
119+ return 0;
120+}
121+
122+char* cdata_statement(){
123+ // 0x00000020, 0x00000021, 0x00000022, and 0x00000023 (add/addu/sub/subu zero,zero,zero)
124+ // are the sign of data region
125+ int beginpos,prevpos;
126+ char* err;
127+ char b1;
128+ char* cpy;
129+ int shift=0;
130+ int i=0;
131+ beginpos=g_objpos;
132+ check_obj_space(2);
133+ g_object[g_objpos++]=0x04110000; // bgezal zero,xxxx
134+ g_object[g_objpos++]=0x00000020; // add zero,zero,zero
135+ next_position();
136+ b1=g_source[g_srcpos];
137+ while('0'<=b1 && b1<='9' || b1=='-' || b1=='$'){
138+ prevpos=g_objpos;
139+ g_valueisconst=1;
140+ err=get_simple_value();
141+ if (!g_valueisconst) err=ERR_SYNTAX;
142+ if (g_intconst<0x00 || 0xff<g_intconst) err=ERR_SYNTAX;
143+ if (err) return err;
144+ g_objpos=prevpos;
145+ i|=g_intconst<<shift;
146+ shift+=8;
147+ if (32<=shift) {
148+ check_obj_space(1);
149+ g_object[g_objpos++]=i;
150+ shift=0;
151+ i=0;
152+ }
153+ next_position();
154+ b1=g_source[g_srcpos];
155+ if (b1!=',') break;
156+ g_srcpos++;
157+ next_position();
158+ b1=g_source[g_srcpos];
159+ if (b1==0x0d || b1==0x0a) {
160+ // Multiline CDATA statement
161+ g_line++;
162+ g_fileline++;
163+ if (b1==0x0D && g_source[g_srcpos+1]==0x0A) g_srcpos++;
164+ g_srcpos++;
165+ // Maintain at least 256 characters in cache.
166+ if (256<=g_srcpos) read_file(256);
167+ next_position();
168+ b1=g_source[g_srcpos];
169+ }
170+ }
171+ // Write the last 1-3 bytes and shift data if total # is not multipes of 4.
172+ if (0<shift) {
173+ // Convert shift value from bit-shift to data byte-shift.
174+ shift=4-shift/8;
175+ check_obj_space(1);
176+ g_object[g_objpos++]=i;
177+ for(cpy=(char*)&g_object[g_objpos]-1;(char*)&g_object[beginpos+2]<cpy;cpy--){
178+ cpy[0]=cpy[0-shift];
179+ }
180+ }
181+ // Determine the size of data
182+ i=g_objpos-beginpos-1;
183+ g_object[beginpos] =0x04110000|i; // bgezal zero,xxxx
184+ g_object[beginpos+1]=0x00000020|shift; // add zero,zero,zero
185+ return 0;
186+}
187+
188+char* data_statement(){
189+ // 0x00000020, 0x00000021, 0x00000022, and 0x00000023 (add/addu/sub/subu zero,zero,zero)
190+ // are the sign of data region
191+ int i,prevpos;
192+ char* err;
193+ while(1){
194+ prevpos=g_objpos;
195+ check_obj_space(2);
196+ g_object[g_objpos++]=0x04110000; // bgezal zero,xxxx
197+ g_object[g_objpos++]=0x00000020; // add zero,zero,zero
198+ next_position();
199+ if (g_source[g_srcpos]=='"') {
200+ // Constant string
201+ // Store pointer to string. This is 3 words bellow of current position
202+ g_object[g_objpos]=(int)(&g_object[g_objpos+3]);
203+ g_objpos++;
204+ g_object[prevpos]=0x04110002; // bgezal zero,xxxx
205+ err=simple_string();
206+ if (err) return err;
207+ next_position();
208+ if (g_source[g_srcpos]==',') {
209+ g_srcpos++;
210+ continue;
211+ }
212+ return 0;
213+ }
214+ err=exec_statement();
215+ if (err) return err;
216+ // Determine the size of data
217+ i=g_objpos-prevpos-1;
218+ g_object[prevpos]=0x04110000|i; // bgezal zero,xxxx
219+ if (g_source[g_srcpos]=='"') {
220+ // Constant string
221+ continue;
222+ }
223+ return 0;
224+ }
225+}
226+
227+char* clear_statement(){
228+ call_lib_code(LIB_CLEAR);
229+ return 0;
230+}
231+
232+char* poke_statement(){
233+ char* err;
234+ err=get_value();
235+ if (err) return err;
236+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
237+ g_srcpos++;
238+ check_obj_space(2);
239+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
240+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
241+ err=get_value();
242+ if (err) return err;
243+ check_obj_space(3);
244+ g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp)
245+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
246+ g_object[g_objpos++]=0xA0620000; // sb v0,0(v1)
247+ return 0;
248+}
249+
250+char* dim_statement(){
251+ char* err;
252+ char b1;
253+ int i;
254+ int spos;
255+ int stack;
256+ while(1){
257+ stack=0;
258+ next_position();
259+ i=get_var_number();
260+ if (i<0) return ERR_SYNTAX;
261+ if (g_source[g_srcpos]=='#') g_srcpos++;
262+ next_position();
263+ if (g_source[g_srcpos]!='(') return ERR_SYNTAX;
264+ check_obj_space(1);
265+ spos=g_objpos++; // addiu sp,sp,xxxx
266+ do {
267+ g_srcpos++;
268+ err=get_value();
269+ if (err) return err;
270+ stack+=4;
271+ check_obj_space(1);
272+ g_object[g_objpos++]=0xAFA20000|stack; // sw v0,8(sp)
273+ } while (g_source[g_srcpos]==',');
274+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
275+ g_srcpos++;
276+ check_obj_space(3);
277+ g_object[g_objpos++]=0x24040000|(i); // addiu a0,zero,xx
278+ g_object[g_objpos++]=0x24050000|(stack/4); // addiu a1,zero,xxxx
279+ g_object[g_objpos++]=0x03A01025; // or v0,sp,zero
280+ call_lib_code(LIB_DIM);
281+ // Stack -/+
282+ check_obj_space(1);
283+ g_object[g_objpos++]=0x27BD0000|stack; // addiu sp,sp,xxxx
284+ stack=(0-stack)&0x0000FFFF;
285+ g_object[spos]=0x27BD0000|stack; // addiu sp,sp,xxxx
286+ next_position();
287+ if (g_source[g_srcpos]!=',') break;
288+ g_srcpos++;
289+ }
290+ return 0;
291+}
292+
293+char* label_statement(){
294+ char* err;
295+ char b1;
296+ b1=g_source[g_srcpos];
297+ if (b1<'A' || 'Z'<b1) return ERR_SYNTAX; // Number is not allowed here.
298+ err=get_label();
299+ if (err) return err;
300+ // Check existing label with the same name here.
301+ if (search_label(g_label)) {
302+ // Error: duplicate labels
303+ printstr("Label ");
304+ printstr(resolve_label(g_label));
305+ return ERR_MULTIPLE_LABEL;
306+ }
307+ check_obj_space(2);
308+ g_object[g_objpos++]=0x3C160000|((g_label>>16)&0x0000FFFF); //lui s6,yyyy;
309+ g_object[g_objpos++]=0x36D60000|(g_label&0x0000FFFF); //ori s6,s6,zzzz;
310+ return 0;
311+}
312+
313+char* restore_statement(){
314+ char* err;
315+ err=get_label();
316+ if (err) return err;
317+ if (g_label) {
318+ // Constant label/number
319+ // Use 32 bit mode also for values<65536
320+ // This code will be replaced to code for v0 for pointer in linker.
321+ check_obj_space(2);
322+ g_object[g_objpos++]=0x3C020000|(g_label>>16); // lui v0,xxxx
323+ g_object[g_objpos++]=0x34420000|(g_label&0x0000FFFF); // ori v0,v0,xxxx
324+ } else {
325+ // Dynamic number
326+ err=get_value();
327+ if (err) return err;
328+ }
329+ call_lib_code(LIB_RESTORE);
330+ return 0;
331+}
332+
333+char* gosub_statement_sub(){
334+ char* err;
335+ err=get_label();
336+ if (err) return err;
337+ if (g_label) {
338+ // Label/number is constant.
339+ // Linker will change following codes later.
340+ // Note that 0x0812xxxx and 0x0813xxxx are specific codes for these.
341+ check_obj_space(6);
342+ g_object[g_objpos++]=0x04130003; // bgezall zero,label1
343+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
344+ g_object[g_objpos++]=0x10000003; // beq zero,zero,label2
345+ g_object[g_objpos++]=0x08120000|((g_label>>16)&0x0000FFFF); // nop
346+ // label1:
347+ g_object[g_objpos++]=0x08130000|(g_label&0x0000FFFF); // j xxxx
348+ g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp)
349+ // label2:
350+ } else {
351+ // Label/number will be dynamically set when executing code.
352+ err=get_value();
353+ if (err) return err;
354+ call_lib_code(LIB_LABEL);
355+ check_obj_space(6);
356+ g_object[g_objpos++]=0x04130003; // bgezall zero,label1
357+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
358+ g_object[g_objpos++]=0x10000003; // beq zero,zero,label2
359+ g_object[g_objpos++]=0x00000000; // nop
360+ // label1:
361+ g_object[g_objpos++]=0x00400008; // jr v0
362+ g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp)
363+ // label2:
364+ }
365+ return 0;
366+}
367+
368+char* gosub_statement(){
369+ char* err;
370+ int opos,spos,stack;
371+ opos=g_objpos;
372+ spos=g_srcpos;
373+ err=gosub_statement_sub();
374+ if (err) return err;
375+ next_position();
376+ // If there is no 2nd argument, return.
377+ if (g_source[g_srcpos]!=',') return 0;
378+
379+ // There is (at least) 2nd argument.
380+ // Rewind object and construct argument-creating routine.
381+ g_objpos=opos;
382+ stack=4;
383+ g_object[g_objpos++]=0x27BD0000; // addiu sp,sp,-xx
384+ do {
385+ g_srcpos++;
386+ stack+=4;
387+ err=get_stringFloatOrValue();
388+ if (err) return err;
389+ check_obj_space(1);
390+ g_object[g_objpos++]=0xAFA20000|stack; // sw v0,xx(sp)
391+ next_position();
392+ } while(g_source[g_srcpos]==',');
393+ check_obj_space(2);
394+ g_object[g_objpos++]=0xAFB50004; // sw s5,4(sp)
395+ g_object[g_objpos++]=0x03A0A821; // addu s5,sp,zero
396+ g_object[opos]|=((0-stack)&0xFFFF); // addiu sp,sp,-xx (See above)
397+ // Rewind source and construct GOSUB routine again.
398+ opos=spos;
399+ spos=g_srcpos;
400+ g_srcpos=opos;
401+ err=gosub_statement_sub();
402+ if (err) return err;
403+ // Remove stack
404+ check_obj_space(2);
405+ g_object[g_objpos++]=0x8FB50004; // lw s5,4(sp)
406+ g_object[g_objpos++]=0x27BD0000|stack; // addiu sp,sp,xx
407+ // All done, go back to wright source position
408+ g_srcpos=spos;
409+ return 0;
410+}
411+
412+char* return_statement(){
413+ char* err;
414+ char b1;
415+ next_position();
416+ b1=g_source[g_srcpos];
417+ if (0x20<b1 && b1!=':') {
418+ // There is a return value.
419+ err=get_stringFloatOrValue();
420+ if (err) return err;
421+ }
422+ check_obj_space(3);
423+ g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp)
424+ g_object[g_objpos++]=0x00600008; // jr v1
425+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
426+ return 0;
427+}
428+
429+char* goto_statement(){
430+ char* err;
431+ err=get_label();
432+ if (err) return err;
433+ if (g_label) {
434+ // Label/number is constant.
435+ // Linker will change following codes later.
436+ // Note that 0x0810xxxx and 0x0811xxxx are specific codes for these.
437+ check_obj_space(2);
438+ g_object[g_objpos++]=0x08100000|((g_label>>16)&0x0000FFFF); // j xxxx
439+ g_object[g_objpos++]=0x08110000|(g_label&0x0000FFFF); // nop
440+ } else {
441+ // Label/number will be dynamically set when executing code.
442+ err=get_value();
443+ if (err) return err;
444+ call_lib_code(LIB_LABEL);
445+ check_obj_space(2);
446+ g_object[g_objpos++]=0x00400008; // jr v0
447+ g_object[g_objpos++]=0x00000000; // nop
448+ }
449+ return 0;
450+}
451+
452+char* if_statement(){
453+ char* err;
454+ int prevpos,bpos;
455+ // Get value.
456+ err=get_floatOrValue();
457+ if (err) return err;
458+ // Check "THEN"
459+ if (!nextCodeIs("THEN")) return ERR_SYNTAX;
460+ // Check if statement follows after THEN statement
461+ next_position();
462+ if (nextCodeIs("REM")) {
463+ // If REM statement follows, skip comment words.
464+ rem_statement();
465+ }
466+ if (g_source[g_srcpos]<0x20) {
467+ // End of line.
468+ // Use IF-THEN-ENDIF mode (multiple line mode)
469+ check_obj_space(3);
470+ g_object[g_objpos++]=0x30000000; // nop (see linker)
471+ g_object[g_objpos++]=0x10400000; // beq v0,zero,xxxx
472+ g_object[g_objpos++]=0x30000000; // nop (see linker)
473+ return 0;
474+ }
475+ // One line mode
476+ // If $v0=0 then skip.
477+ bpos=g_objpos;
478+ check_obj_space(2);
479+ g_object[g_objpos++]=0x10400000; // beq v0,zero,xxxx
480+ g_object[g_objpos++]=0x00000000; // nop
481+ prevpos=g_srcpos;
482+ if (statement()) {
483+ // May be label
484+ g_srcpos=prevpos;
485+ err=goto_statement();
486+ if (err) return err;
487+ } else {
488+ // Must be statement(s)
489+ while(1) {
490+ if (g_source[g_srcpos]!=':') break;
491+ g_srcpos++;
492+ err=statement();
493+ if (err) return err;
494+ }
495+ }
496+ // Check if "ELSE" exists.
497+ if (!nextCodeIs("ELSE ")) {
498+ // "ELSE" not found. This is the end of "IF" statement.
499+ // Previous branch command must jump to this position.
500+ g_object[bpos]=0x10400000|(g_objpos-bpos-1); // beq v0,zero,xxxx
501+ return 0;
502+ }
503+ // Skip after ELSE if required.
504+ check_obj_space(2);
505+ g_object[g_objpos++]=0x10000000; // beq zero,zero,xxxx
506+ g_object[g_objpos++]=0x00000000; // nop
507+ // Previous branch command must jump to this position.
508+ g_object[bpos]=0x10400000|(g_objpos-bpos-1); // beq v0,zero,xxxx
509+ bpos=g_objpos-2;
510+ // Next statement is either label or general statement
511+ prevpos=g_srcpos;
512+ if (statement()) {
513+ // May be label
514+ g_srcpos=prevpos;
515+ err=goto_statement();
516+ if (err) return err;
517+ } else {
518+ // Must be statement(s)
519+ while(1) {
520+ if (g_source[g_srcpos]!=':') break;
521+ g_srcpos++;
522+ err=statement();
523+ if (err) return err;
524+ }
525+ }
526+ // Previous branch command must jump to this position.
527+ g_object[bpos]=0x10000000|(g_objpos-bpos-1); // beq zero,zero,xxxx
528+ return 0;
529+}
530+
531+char* elseif_statement(void){
532+ // Multiple line mode
533+ char* err;
534+ g_object[g_objpos++]=0x08160100; // breakif (see linker)
535+ g_object[g_objpos++]=0x30008000; // nop (see linker)
536+ // Get value.
537+ err=get_floatOrValue();
538+ if (err) return err;
539+ // Check "THEN"
540+ if (!nextCodeIs("THEN")) return ERR_SYNTAX;
541+ // Check if statement follows after THEN statement
542+ if (nextCodeIs("REM")) {
543+ // If REM statement follows, skip comment words.
544+ rem_statement();
545+ }
546+ if (0x20<=g_source[g_srcpos]) return ERR_SYNTAX;
547+ // Statement didn't follow after THEM statement (that is correct).
548+ g_object[g_objpos++]=0x10400000; // beq v0,zero,xxxx
549+ g_object[g_objpos++]=0x30000000; // nop (see linker)
550+ return 0;
551+
552+}
553+
554+char* else_statement(void){
555+ // Multiple line mode
556+ g_object[g_objpos++]=0x08160100; // breakif (see linker)
557+ g_object[g_objpos++]=0x30008000; // nop (see linker)
558+ g_object[g_objpos++]=0x30000000; // nop (see linker)
559+ // Check if statement follows after THEN statement
560+ if (nextCodeIs("REM")) {
561+ // If REM statement follows, skip comment words.
562+ rem_statement();
563+ }
564+ if (0x20<=g_source[g_srcpos]) return ERR_SYNTAX;
565+ // Statement didn't follow after THEM statement (that is correct).
566+ return 0;
567+}
568+
569+char* endif_statement(void){
570+ // Multiple line mode
571+ g_object[g_objpos++]=0x30008000; // nop (see linker)
572+ g_object[g_objpos++]=0x30008000; // nop (see linker)
573+ // Check if statement follows after THEN statement
574+ if (nextCodeIs("REM")) {
575+ // If REM statement follows, skip comment words.
576+ rem_statement();
577+ }
578+ if (0x20<=g_source[g_srcpos]) return ERR_SYNTAX;
579+ // Statement didn't follow after THEM statement (that is correct).
580+ return 0;
581+}
582+
583+char* end_statement(void){
584+ int i;
585+ i=(int)&g_end_addr;
586+ i-=g_gp;
587+ check_obj_space(3);
588+ g_object[g_objpos++]=0x8F820000|(i&0x0000FFFF); // lw v0,xxxx(gp)
589+ g_object[g_objpos++]=0x00400008; // jr v0
590+ g_object[g_objpos++]=0x00000000; // nop
591+ return 0;
592+}
593+
594+char* let_dim_sub(int i){
595+ char* err;
596+ g_srcpos++;
597+ err=get_value();
598+ if (err) return err;
599+ check_obj_space(4);
600+ g_object[g_objpos++]=0x00021080; // sll v0,v0,0x2
601+ g_object[g_objpos++]=0x8FC30000|(i*4); // lw v1,xx(s8)
602+ g_object[g_objpos++]=0x00621821; // addu v1,v1,v0
603+ g_object[g_objpos++]=0xAFA30004; // sw v1,4(sp)
604+ while(g_source[g_srcpos]==','){
605+ g_srcpos++;
606+ err=get_value();
607+ if (err) return err;
608+ check_obj_space(4);
609+ g_object[g_objpos++]=0x00021080; // sll v0,v0,0x2
610+ g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp)
611+ g_object[g_objpos++]=0x8C630000; // lw v1,0(v1)
612+ g_object[g_objpos++]=0x00621821; // addu v1,v1,v0
613+ g_object[g_objpos++]=0xAFA30004; // sw v1,4(sp)
614+ }
615+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
616+ g_srcpos++;
617+ return 0;
618+};
619+
620+char* let_statement(){
621+ char* err;
622+ char b2,b3;
623+ int i;
624+ next_position();
625+ i=get_var_number();
626+ if (i<0) return ERR_SYNTAX;
627+ b2=g_source[g_srcpos];
628+ b3=g_source[g_srcpos+1];
629+ if (b2=='#' && b3=='(') {
630+ // Float dimension
631+ g_srcpos++;
632+ check_obj_space(1);
633+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
634+ let_dim_sub(i);
635+ next_position();
636+ if (g_source[g_srcpos]!='=') return ERR_SYNTAX;
637+ g_srcpos++;
638+ err=get_float();
639+ if (err) return err;
640+ check_obj_space(3);
641+ g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp)
642+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
643+ g_object[g_objpos++]=0xAC620000; // sw v0,0(v1)
644+ return 0;
645+ } else if (b2=='#') {
646+ // Float A-Z
647+ g_srcpos++;
648+ next_position();
649+ if (g_source[g_srcpos]!='=') return ERR_SYNTAX;
650+ g_srcpos++;
651+ err=get_float();
652+ if (err) return err;
653+ check_obj_space(1);
654+ g_object[g_objpos++]=0xAFC20000|(i*4); // sw v0,xxx(s8)
655+ return 0;
656+ } else if (b2=='$') {
657+ // String
658+ g_srcpos++;
659+ next_position();
660+ if (g_source[g_srcpos]!='=') return ERR_SYNTAX;
661+ g_srcpos++;
662+ err=get_string();
663+ if (err) return err;
664+ check_obj_space(1);
665+ g_object[g_objpos++]=0x24040000|(i); //addiu a0,zero,xx
666+ call_lib_code(LIB_LETSTR);
667+ return 0;
668+ } else if (b2=='(') {
669+ // Dimension
670+ check_obj_space(1);
671+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
672+ let_dim_sub(i);
673+ next_position();
674+ if (g_source[g_srcpos]!='=') return ERR_SYNTAX;
675+ g_srcpos++;
676+ err=get_value();
677+ if (err) return err;
678+ check_obj_space(3);
679+ g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp)
680+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
681+ g_object[g_objpos++]=0xAC620000; // sw v0,0(v1)
682+ return 0;
683+ } else {
684+ // Integer A-Z
685+ next_position();
686+ if (g_source[g_srcpos]!='=') return ERR_SYNTAX;
687+ g_srcpos++;
688+ err=get_value();
689+ if (err) return err;
690+ check_obj_space(1);
691+ g_object[g_objpos++]=0xAFC20000|(i*4); // sw v0,xxx(s8)
692+ }
693+ return 0;
694+}
695+
696+char* print_statement_main(enum libs lib_printstr, enum libs lib_string){
697+ char* err;
698+ char b1;
699+ int i;
700+ int status=0;// 1:',' 2:';' 0:none
701+ while(1){
702+ next_position();
703+ if (endOfStatement()) break;
704+ if (!strncmp(g_source+g_srcpos,"ELSE " ,5)) break;
705+ err=get_stringFloatOrValue();
706+ if (err) return err;
707+ switch(g_lastvar){
708+ case VAR_INTEGER:
709+ // Use DEC$() function.
710+ call_lib_code(LIB_DEC);
711+ break;
712+ case VAR_FLOAT:
713+ // Use FLOAT$() function.
714+ check_obj_space(2);
715+ g_object[g_objpos++]=0x00022021; //addu a0,zero,v0
716+ g_object[g_objpos++]=0x34020000; //ori v0,zero,0x0000
717+ call_lib_code(LIB_SPRINTF);
718+ break;
719+ case VAR_STRING:
720+ default:
721+ break;
722+ }
723+ // Call printstr() function
724+ // First argument is the pointer to string
725+ call_lib_code(lib_printstr);
726+ next_position();
727+ b1=g_source[g_srcpos];
728+ if (b1==',') {
729+ status=1;
730+ g_srcpos++;
731+ // Call lib_string() function for comma (,)
732+ check_obj_space(1);
733+ g_object[g_objpos++]=0x34020001; // ori v0,zero,1
734+ call_lib_code(lib_string);
735+ } else if (b1==';') {
736+ status=2;
737+ g_srcpos++;
738+ } else {
739+ status=0;
740+ }
741+ }
742+ if (status==0) {
743+ // Call lib_string() function for CR (\n)
744+ check_obj_space(1);
745+ g_object[g_objpos++]=0x34020000; // ori v0,zero,0
746+ call_lib_code(lib_string);
747+ }
748+ return 0;
749+}
750+
751+char* break_statement(){
752+ check_obj_space(2);
753+ g_object[g_objpos++]=0x08160000; // j xxxx (See link() function)
754+ g_object[g_objpos++]=0x00000000; // nop
755+ return 0;
756+}
757+
758+char* continue_statement(){
759+ check_obj_space(2);
760+ g_object[g_objpos++]=0x08160008; // j xxxx (See link() function)
761+ g_object[g_objpos++]=0x00000000; // nop
762+ return 0;
763+}
764+
765+char* for_statement(){
766+ char* err;
767+// char b1;
768+ int i;
769+ int prepos=g_srcpos;
770+ // Initialization of variable
771+// next_position();
772+// b1=g_source[g_srcpos];
773+ i=get_var_number();
774+// if (b1<'A' || 'Z'<b1) return ERR_SYNTAX;
775+ if (i<0) return ERR_SYNTAX;
776+ g_srcpos=prepos;
777+ err=let_statement();
778+ if (err) return err;
779+ // Check if "TO" exists
780+ if (!nextCodeIs("TO ")) return ERR_SYNTAX;
781+ err=get_value();
782+ if (err) return err;
783+ // Usage of stack:
784+ // 12(sp): "TO" value
785+ // 8(sp): "STEP" value
786+ // 4(sp): Address to return to in "NEXT" statement.
787+ // Store "TO" value in stack
788+ check_obj_space(2);
789+ g_object[g_objpos++]=0x0820FFF4; // addiu sp,sp,-12 (see linker)
790+ g_object[g_objpos++]=0xAFA2000C; // sw v0,12(sp)
791+ // Check if "STEP" exists
792+ g_valueisconst=1;
793+ if (nextCodeIs("STEP ")) {
794+ // "STEP" exists. Get value
795+ err=get_value();
796+ if (err) return err;
797+ } else {
798+ // "STEP" not exist. Use "1".
799+ check_obj_space(1);
800+ g_object[g_objpos++]=0x24020001; // addiu v0,zero,1
801+ g_intconst=1;
802+ }
803+ check_obj_space(14);
804+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp) (STEP value)
805+ g_object[g_objpos++]=0x04130004; // bgezall zero,check
806+// g_object[g_objpos++]=0x8FC40000|((b1-'A')*4); // lw a0,xx(s8) (current var value)
807+ g_object[g_objpos++]=0x8FC40000|(i*4); // lw a0,xx(s8) (current var value)
808+ // After executing "NEXT" statement, process reaches following line.
809+ // Update variable value by adding STEP value
810+ // Note that STEP value is loaded onto $v0 in NEXT statement
811+// g_object[g_objpos++]=0x8FC40000|((b1-'A')*4); // lw a0,xx(s8) (current var value)
812+ g_object[g_objpos++]=0x8FC40000|(i*4); // lw a0,xx(s8) (current var value)
813+ g_object[g_objpos++]=0x00822021; // addu a0,a0,v0
814+// g_object[g_objpos++]=0xAFC40000|((b1-'A')*4); // sw a0,xx(s8) (new var value)
815+ g_object[g_objpos++]=0xAFC40000|(i*4); // sw a0,xx(s8) (new var value)
816+ // Value-checking routine and storing ra in stack
817+ // check:
818+ g_object[g_objpos++]=0x8FA3000C; // lw v1,12(sp) (TO value)
819+ g_object[g_objpos++]=0x00641823; // subu v1,v1,a0
820+ g_object[g_objpos++]=0x04420001; // bltzl v0,negative
821+ g_object[g_objpos++]=0x00031823; // subu v1,zero,v1
822+ // negative:
823+ g_object[g_objpos++]=0x04610003; // bgez v1,continue
824+ g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp)
825+ break_statement(); // (2 words)
826+ // continue:
827+ return 0;
828+}
829+
830+char* next_statement(){
831+ // Return to address stored in 4($sp)
832+ // while set $v0 to 8($sp) (see for_statement)
833+ // Following assembly must be 4 words.
834+ // If the number of words will be changed, link.c must be reviced for CONTINUE statement.
835+ check_obj_space(4);
836+ g_object[g_objpos++]=0x8FBF0004; // lw ra,4(sp)
837+ g_object[g_objpos++]=0x03E00008; // jr ra
838+ g_object[g_objpos++]=0x8FA20008; // lw v0,8(sp) (STEP value)
839+ g_object[g_objpos++]=0x0830000C; // addiu sp,sp,12 (see linker)
840+ return 0;
841+}
842+
843+char* do_statement(){
844+ char* err;
845+ // Usage of stack:
846+ // 4(sp): Address to return to in "DO" statement.
847+ check_obj_space(3);
848+ g_object[g_objpos++]=0x04130001;// bgezall zero,label1:
849+ g_object[g_objpos++]=0x0822FFFC;// addiu sp,sp,-4 (see linker)
850+ // label1:
851+ g_object[g_objpos++]=0xAFBF0004;// sw ra,4(sp)
852+ if (nextCodeIs("WHILE ")) {
853+ // DO WHILE
854+ err=get_floatOrValue();
855+ if (err) return err;
856+ check_obj_space(2);
857+ g_object[g_objpos++]=0x14400003; // bne v0,zero,labe2
858+ g_object[g_objpos++]=0x00000000; // nop
859+ return break_statement(); // (2 words)
860+ // label2:
861+
862+ } else if (nextCodeIs("UNTIL ")) {
863+ // DO UNTIL
864+ err=get_floatOrValue();
865+ if (err) return err;
866+ check_obj_space(2);
867+ g_object[g_objpos++]=0x10400003; // beq v0,zero,label2
868+ g_object[g_objpos++]=0x00000000; // nop
869+ return break_statement(); // (2 words)
870+ // label2:
871+ } else {
872+ // DO statement without WHILE/UNTIL
873+ return 0;
874+ }
875+}
876+
877+char* loop_statement(){
878+ char* err;
879+ int opos;
880+ opos=g_objpos;
881+ if (nextCodeIs("WHILE ")) {
882+ // LOOP WHILE
883+ err=get_floatOrValue();
884+ if (err) return err;
885+ check_obj_space(1);
886+ g_object[g_objpos++]=0x10400003; // beq v0,zero,label1
887+ } else if (nextCodeIs("UNTIL ")) {
888+ // LOOP UNTIL
889+ err=get_floatOrValue();
890+ if (err) return err;
891+ check_obj_space(1);
892+ g_object[g_objpos++]=0x14400003; // bne v0,zero,label
893+ } else {
894+ // LOOP statement without WHILE/UNTIL
895+ }
896+ check_obj_space(4);
897+ g_object[g_objpos++]=0x8FBF0004; // lw ra,4(sp)
898+ g_object[g_objpos++]=0x03E00008; // jr ra
899+ opos=g_objpos+1-opos;
900+ g_object[g_objpos++]=0x3000F000|opos; // nop (See linker, used for CONTINUE statement)
901+ // label1:
902+ g_object[g_objpos++]=0x08320004; // addiu sp,sp,4 (See link() function)
903+ return 0;
904+}
905+
906+char* while_statement(){
907+ char* err;
908+ check_obj_space(3);
909+ g_object[g_objpos++]=0x04130001; // bgezall zero,label1:
910+ g_object[g_objpos++]=0x0821FFFC; // addiu sp,sp,-4 (see linker)
911+ // label1:
912+ g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp)
913+ err=get_floatOrValue();
914+ if (err) return err;
915+ check_obj_space(2);
916+ g_object[g_objpos++]=0x14400003; // bne v0,zero,label2
917+ g_object[g_objpos++]=0x00000000; // nop
918+ return break_statement(); // (2 words)
919+ // label2:
920+}
921+
922+char* wend_statement(){
923+ check_obj_space(4);
924+ g_object[g_objpos++]=0x8FBF0004; // lw ra,4(sp)
925+ g_object[g_objpos++]=0x03E00008; // jr ra
926+ g_object[g_objpos++]=0x3000F003; // nop (See linker, used for CONTINUE statement)
927+ // label1:
928+ g_object[g_objpos++]=0x08310004; // addiu sp,sp,4 (See link() function)
929+ return 0;
930+}
931+
932+char* param4_statement(enum libs lib){
933+ // lib is either LIB_PALETTE or LIB_GPALETTE
934+ // PALETTE N,R,G,B
935+ char* err;
936+ // Get N
937+ err=get_value();
938+ if (err) return err;
939+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
940+ g_srcpos++;
941+ check_obj_space(2);
942+ g_object[g_objpos++]=0x27BDFFF4; // addiu sp,sp,-12
943+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
944+ // Get R
945+ err=get_value();
946+ if (err) return err;
947+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
948+ g_srcpos++;
949+ check_obj_space(1);
950+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
951+ // Get G
952+ err=get_value();
953+ if (err) return err;
954+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
955+ g_srcpos++;
956+ check_obj_space(1);
957+ g_object[g_objpos++]=0xAFA2000C; // sw v0,12(sp)
958+ // Get B
959+ err=get_value();
960+ if (err) return err;
961+ call_lib_code(lib);
962+ check_obj_space(1);
963+ g_object[g_objpos++]=0x27BD000C; // addiu sp,sp,12
964+ return 0;
965+}
966+
967+char* param3_statement(enum libs lib){
968+ char* err;
969+ // Get 1st parameter
970+ err=get_value();
971+ if (err) return err;
972+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
973+ g_srcpos++;
974+ check_obj_space(2);
975+ g_object[g_objpos++]=0x27BDFFF8; // addiu sp,sp,-8
976+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
977+ // Get 2nd parameter
978+ err=get_value();
979+ if (err) return err;
980+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
981+ g_srcpos++;
982+ check_obj_space(1);
983+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
984+ // Get 3rd parameter
985+ err=get_value();
986+ if (err) return err;
987+ call_lib_code(lib);
988+ check_obj_space(1);
989+ g_object[g_objpos++]=0x27BD0008; // addiu sp,sp,8
990+ return 0;
991+}
992+
993+char* bgcolor_statement(){
994+ // BGCOLOR R,G,B
995+ return param3_statement(LIB_BGCOLOR);
996+}
997+
998+char* pcg_statement(){
999+ // PCG ASCII,D1,D2
1000+ return param3_statement(LIB_PCG);
1001+}
1002+
1003+char* usepcg_statement(){
1004+ int objpos=g_objpos;
1005+ if (get_value()) {
1006+ // Getting integer failed.
1007+ // It supporsed to be not parameter
1008+ // and same as parameter=1.
1009+ g_objpos=objpos;
1010+ check_obj_space(1);
1011+ g_object[g_objpos++]=0x34020001; //ori v0,zero,0x01
1012+ }
1013+ call_lib_code(LIB_USEPCG);
1014+ return 0;
1015+}
1016+
1017+char* usegraphic_statement(){
1018+ int objpos=g_objpos;
1019+ if (get_value()) {
1020+ // Getting integer failed.
1021+ // It supporsed to be not parameter
1022+ // and same as parameter=1.
1023+ g_objpos=objpos;
1024+ check_obj_space(1);
1025+ g_object[g_objpos++]=0x34020001; //ori v0,zero,0x01
1026+ }
1027+ call_lib_code(LIB_USEGRAPHIC);
1028+ return 0;
1029+}
1030+
1031+char* cls_statement(){
1032+ call_lib_code(LIB_CLS);
1033+ return 0;
1034+}
1035+
1036+char* gcls_statement(){
1037+ call_lib_code(LIB_GCLS);
1038+ return 0;
1039+}
1040+
1041+char* color_statement(){
1042+ char* err;
1043+ err=get_value();
1044+ if (err) return err;
1045+ call_lib_code(LIB_COLOR);
1046+ return 0;
1047+}
1048+
1049+char* gcolor_statement(){
1050+ char* err;
1051+ err=get_value();
1052+ if (err) return err;
1053+ call_lib_code(LIB_GCOLOR);
1054+ return 0;
1055+}
1056+
1057+char* param2_statement(enum libs lib){
1058+ char* err;
1059+ // Get 1st
1060+ err=get_value();
1061+ if (err) return err;
1062+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1063+ g_srcpos++;
1064+ check_obj_space(2);
1065+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
1066+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
1067+ // Get 2nd
1068+ err=get_value();
1069+ if (err) return err;
1070+ call_lib_code(lib);
1071+ check_obj_space(1);
1072+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
1073+ return 0;
1074+}
1075+
1076+char* system_statement(){
1077+ // SYSTEM X,Y
1078+ char* err;
1079+ // Get 1st
1080+ err=get_value();
1081+ if (err) return err;
1082+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1083+ g_srcpos++;
1084+ check_obj_space(2);
1085+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
1086+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
1087+ // Get 2nd
1088+ err=get_value();
1089+ if (err) return err;
1090+ check_obj_space(2);
1091+ g_object[g_objpos++]=0x8FA40004; // lw a0,4(sp)
1092+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
1093+ call_lib_code(LIB_SYSTEM);
1094+ return 0;
1095+}
1096+
1097+char* cursor_statement(){
1098+ // CURSOR X,Y
1099+ return param2_statement(LIB_CURSOR);
1100+}
1101+
1102+char* scroll_statement(){
1103+ // SCROLL X,Y
1104+ return param2_statement(LIB_SCROLL);
1105+}
1106+
1107+char* drawcount_statement(){
1108+ char* err;
1109+ err=get_value();
1110+ if (err) return err;
1111+ call_lib_code(LIB_SETDRAWCOUNT);
1112+ return 0;
1113+}
1114+
1115+char* wait_statement(){
1116+ char* err;
1117+ err=get_value();
1118+ if (err) return err;
1119+ call_lib_code(LIB_WAIT);
1120+ return 0;
1121+}
1122+
1123+char* width_statement(){
1124+ char* err;
1125+ err=get_value();
1126+ if (err) return err;
1127+ call_lib_code(LIB_WIDTH);
1128+ return 0;
1129+}
1130+
1131+char* var_statement_sub(int a0, int a1){
1132+ // Construct parameter-setting scripts
1133+ if (a0&0xffff0000) {
1134+ check_obj_space(1);
1135+ g_object[g_objpos++]=0x3C040000|(a0>>16); // lui a0,XXXX
1136+ if (a0&0x0000ffff) {
1137+ check_obj_space(1);
1138+ g_object[g_objpos++]=0x34840000|(a0&0xffff); // ori a0,a0,XXXX
1139+ }
1140+ } else if (a0&0x0000ffff) {
1141+ check_obj_space(1);
1142+ g_object[g_objpos++]=0x34040000|(a0&0xffff); // ori a0,zero,xxxx
1143+ }
1144+ if (a1&0xffff0000) {
1145+ check_obj_space(1);
1146+ g_object[g_objpos++]=0x3C050000|(a1>>16); // lui a1,XXXX
1147+ if (a1&0x0000ffff) {
1148+ check_obj_space(1);
1149+ g_object[g_objpos++]=0x34A50000|(a1&0xffff); // ori a1,a1,XXXX
1150+ }
1151+ } else if (a1&0x0000ffff) {
1152+ check_obj_space(1);
1153+ g_object[g_objpos++]=0x34050000|(a1&0xffff); // ori a1,zero,xxxx
1154+ } else if (a0&0xff000000) {
1155+ // # of variables is 4. Reset $a1 to let lib_var() know that there is no more variables to store.
1156+ check_obj_space(1);
1157+ g_object[g_objpos++]=0x34050000; // ori a1,zero,0
1158+ }
1159+ return 0;
1160+}
1161+
1162+char* var_statement(){
1163+ char* err;
1164+ int i,j,a0,a1;
1165+ static int prevpos;
1166+ short stack;
1167+ do {
1168+ // For stack, 4 bytes are used for return address,
1169+ // 4 bytes are used in lib_var(),
1170+ // and additinal bytes are used for storing variable values.
1171+ stack=8;
1172+ a0=a1=0;
1173+ for (i=0;i<8;i++){
1174+ // Determine the variable number from source code
1175+ j=get_var_number();
1176+ if (j<0) return ERR_SYNTAX;
1177+ stack+=4;
1178+ // Create parameters in $a0, or $a1
1179+ if (i<4) {
1180+ a0=(a0<<8)|(j+1);
1181+ } else {
1182+ a1=(a1<<8)|(j+1);
1183+ }
1184+ // Check remaining variable(s)
1185+ if (g_source[g_srcpos]=='#' || g_source[g_srcpos]=='$') g_srcpos++;
1186+ next_position();
1187+ if (g_source[g_srcpos]!=',') break;
1188+ g_srcpos++;
1189+ }
1190+ // Jump to push routine, first
1191+ check_obj_space(2);
1192+ prevpos=g_objpos;
1193+ g_object[g_objpos++]=0x04130000; // bgezall zero,label1
1194+ g_object[g_objpos++]=0x27BD0000|((0-stack)&0xffff); // addiu sp,sp,-xx
1195+ // Process will be here after RETURN statement
1196+ // Pop routine
1197+ err=var_statement_sub(a0,a1); // Prepare a0, and a1
1198+ if (err) return err;
1199+ call_lib_code(LIB_VAR_POP);
1200+ // Restore stack and return
1201+ check_obj_space(3);
1202+ g_object[g_objpos++]=0x8FA30000|stack; // lw v1,xx(sp)
1203+ g_object[g_objpos++]=0x00600008; // jr v1
1204+ g_object[g_objpos++]=0x27BD0000|stack; // addiu sp,sp,xx
1205+ // Push rotine
1206+ g_object[prevpos]|=g_objpos-prevpos-1; // label1:
1207+ check_obj_space(1);
1208+ g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp)
1209+ err=var_statement_sub(a0,a1); // Prepare a0, and a1
1210+ if (err) return err;
1211+ call_lib_code(LIB_VAR_PUSH);
1212+
1213+ } while (g_source[g_srcpos-1]==',');
1214+ return 0;
1215+}
1216+
1217+
1218+char* graphic_statement(enum functions func){
1219+ /*
1220+ PSET X1,Y1[,C]
1221+ LINE X1,Y1,X2,Y2[,C]
1222+ BOXFILL X1,Y1,X2,Y2[,C]
1223+ CIRCLE X1,Y1,R[,C]
1224+ CIRCLEFILL X1,Y1,R[,C]
1225+ GPRINT X1,Y1,C,BC,S$
1226+ PUTBMP X1,Y1,M,N,BMP
1227+ 4(sp): X1
1228+ 8(sp): Y1
1229+ 12(sp): X2/R/M
1230+ 16(sp): Y2/N
1231+ v0: C/S$/BMP
1232+ */
1233+ char* err;
1234+ int paramnum;
1235+ switch(func){
1236+ case FUNC_PSET:// X1,Y1[,C]
1237+ case FUNC_GCOLOR:// X1,Y1
1238+ case FUNC_POINT:// X1,Y1
1239+ paramnum=2;
1240+ break;
1241+ case FUNC_CIRCLE:// X1,Y1,R[,C]
1242+ case FUNC_CIRCLEFILL:// X1,Y1,R[,C]
1243+ paramnum=3;
1244+ break;
1245+ case FUNC_LINE:// X1,Y1,X2,Y2[,C]
1246+ case FUNC_BOXFILL:// X1,Y1,X2,Y2[,C]
1247+ paramnum=4;
1248+ break;
1249+ case FUNC_GPRINT:// X1,Y1,C,BC,S$
1250+ case FUNC_PUTBMP:// X1,Y1,M,N,BMP
1251+ paramnum=5;
1252+ break;
1253+ default:
1254+ return ERR_UNKNOWN;
1255+ }
1256+
1257+ next_position();
1258+ if (g_source[g_srcpos]==',') {
1259+ // X1 and Y1 is omitted. Set 0x80000000 for both.
1260+ check_obj_space(4);
1261+ g_object[g_objpos++]=0x27BDFFF0; // addiu sp,sp,-16
1262+ g_object[g_objpos++]=0x3C028000; // lui v0,0x0080
1263+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
1264+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
1265+ } else {
1266+ // X1
1267+ err=get_value();
1268+ if (err) return err;
1269+ check_obj_space(2);
1270+ g_object[g_objpos++]=0x27BDFFF0; // addiu sp,sp,-16
1271+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
1272+ // Y1
1273+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1274+ g_srcpos++;
1275+ err=get_value();
1276+ if (err) return err;
1277+ check_obj_space(1);
1278+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
1279+ }
1280+ if (2<paramnum) {
1281+ // X2, R, or M
1282+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1283+ g_srcpos++;
1284+ err=get_value();
1285+ if (err) return err;
1286+ check_obj_space(1);
1287+ g_object[g_objpos++]=0xAFA2000C; // sw v0,12(sp)
1288+ if (3<paramnum) {
1289+ // Y2, BC, or N
1290+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1291+ g_srcpos++;
1292+ err=get_value();
1293+ if (err) return err;
1294+ check_obj_space(1);
1295+ g_object[g_objpos++]=0xAFA20010; // sw v0,16(sp)
1296+ }
1297+ }
1298+ if (func==FUNC_GPRINT) {
1299+ // S$
1300+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1301+ g_srcpos++;
1302+ err=get_string();
1303+ if (err) return err;
1304+ } else if (func==FUNC_PUTBMP) {
1305+ // BMP
1306+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1307+ g_srcpos++;
1308+ err=get_label();
1309+ if (g_label && !err) {
1310+ // Label/number is constant.
1311+ // Linker will change following codes later.
1312+ // Note that 0x0814xxxx and 0x0815xxxx are specific codes for these.
1313+ check_obj_space(2);
1314+ g_object[g_objpos++]=0x08140000|((g_label>>16)&0x0000FFFF); // lui v0,xxxx
1315+ g_object[g_objpos++]=0x08150000|(g_label&0x0000FFFF); // ori v0,v0,xxxx
1316+ // Change func to FUNC_PUTBMP2 (label mode).
1317+ func=FUNC_PUTBMP2;
1318+ } else {
1319+ err=get_value();
1320+ if (err) return err;
1321+ }
1322+ } else {
1323+ // [,C]
1324+ if (g_source[g_srcpos]==',') {
1325+ g_srcpos++;
1326+ err=get_value();
1327+ if (err) return err;
1328+ } else {
1329+ // If C is omitted, use -1.
1330+ check_obj_space(1);
1331+ g_object[g_objpos++]=0x2402FFFF; // addiu v0,zero,-1
1332+ }
1333+ }
1334+ // Call library
1335+ call_lib_code(LIB_GRAPHIC | func);
1336+ // Restore stack pointer
1337+ check_obj_space(1);
1338+ g_object[g_objpos++]=0x27BD0010; // addiu sp,sp,16
1339+ return 0;
1340+}
1341+
1342+char* fopen_statement_main(enum functions func){
1343+ // func is either FUNC_FOPENST or FUNC_FOPEN
1344+ char* err;
1345+ // Get 1st
1346+ err=get_string();
1347+ if (err) return err;
1348+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1349+ g_srcpos++;
1350+ check_obj_space(2);
1351+ g_object[g_objpos++]=0x27BDFFF8; // addiu sp,sp,-8
1352+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
1353+ // Get 2nd
1354+ err=get_string();
1355+ if (err) return err;
1356+ check_obj_space(1);
1357+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
1358+ // Get 3rd
1359+ if (g_source[g_srcpos]==',') {
1360+ g_srcpos++;
1361+ err=get_value();
1362+ if (err) return err;
1363+ } else {
1364+ // If 3rd parameter is omitted, use 0.
1365+ check_obj_space(1);
1366+ g_object[g_objpos++]=0x24020000; // addiu v0,zero,0
1367+ }
1368+ call_lib_code(LIB_FILE | func);
1369+ check_obj_space(1);
1370+ g_object[g_objpos++]=0x27BD0008; // addiu sp,sp,8
1371+ return 0;
1372+}
1373+
1374+char* file_statement(){
1375+ char* err;
1376+ err=get_value();
1377+ if (err) return err;
1378+ call_lib_code(LIB_FILE | FUNC_FILE);
1379+ return 0;
1380+}
1381+
1382+char* fclose_statement(){
1383+ char* err;
1384+ int orgpos=g_srcpos;
1385+ if (endOfStatement()) {
1386+ // If no argument, use 0
1387+ check_obj_space(1);
1388+ g_object[g_objpos++]=0x24020000; // addiu v0,zero,0
1389+ } else {
1390+ err=get_value();
1391+ if (err) return err;
1392+ }
1393+ call_lib_code(LIB_FILE | FUNC_FCLOSE);
1394+ return 0;
1395+}
1396+
1397+char* fget_statement(){
1398+ return param2_statement(LIB_FILE | FUNC_FGET);
1399+}
1400+
1401+char* fput_statement(){
1402+ return param2_statement(LIB_FILE | FUNC_FPUT);
1403+}
1404+
1405+char* fseek_statement(){
1406+ char* err;
1407+ err=get_value();
1408+ if (err) return err;
1409+ call_lib_code(LIB_FILE | FUNC_FSEEK);
1410+ return 0;
1411+}
1412+
1413+char* fputc_statement(){
1414+ char* err;
1415+ err=get_value();
1416+ if (err) return err;
1417+ call_lib_code(LIB_FILE | FUNC_FPUTC);
1418+ return 0;
1419+}
1420+
1421+char* fremove_statement(){
1422+ char* err;
1423+ err=get_string();
1424+ if (err) return err;
1425+ call_lib_code(LIB_FILE | FUNC_FREMOVE);
1426+ return 0;
1427+}
1428+
1429+char* usevar_statement(){
1430+ char* err;
1431+ int i;
1432+ do {
1433+ next_position();
1434+ i=check_var_name();
1435+ if (i<65536) return ERR_SYNTAX;
1436+ err=register_var_name(i);
1437+ if (err) return err;
1438+ if (g_source[g_srcpos]=='#' || g_source[g_srcpos]=='$') g_srcpos++;
1439+ next_position();
1440+ if (g_source[g_srcpos]==',') {
1441+ g_srcpos++;
1442+ } else {
1443+ break;
1444+ }
1445+ } while(1);
1446+ return 0;
1447+}
1448+
1449+char* playwave_statement(){
1450+ char* err;
1451+ err=get_string();
1452+ if (err) return err;
1453+ check_obj_space(2);
1454+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
1455+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
1456+ if (g_source[g_srcpos]==',') {
1457+ g_srcpos++;
1458+ // Get 2nd
1459+ err=get_value();
1460+ if (err) return err;
1461+ } else {
1462+ // If 2rd parameter is omitted, use 0.
1463+ check_obj_space(1);
1464+ g_object[g_objpos++]=0x24020000; // addiu v0,zero,0
1465+ }
1466+ call_lib_code(LIB_PLAYWAVE);
1467+ check_obj_space(1);
1468+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
1469+ return 0;
1470+}
1471+
1472+#ifdef __DEBUG
1473+ char* debug_statement(){
1474+ call_lib_code(LIB_DEBUG);
1475+ return 0;
1476+ }
1477+#endif
1478+
1479+// Aliases follow
1480+
1481+char* palette_statement(){
1482+ return param4_statement(LIB_PALETTE);
1483+}
1484+
1485+char* gpalette_statement(){
1486+ return param4_statement(LIB_GPALETTE);
1487+}
1488+
1489+char* print_statement(){
1490+ return print_statement_main(LIB_PRINTSTR,LIB_STRING);
1491+}
1492+
1493+char* pset_statement(){
1494+ return graphic_statement(FUNC_PSET);
1495+}
1496+
1497+char* line_statement(){
1498+ return graphic_statement(FUNC_LINE);
1499+}
1500+
1501+char* boxfill_statement(){
1502+ return graphic_statement(FUNC_BOXFILL);
1503+}
1504+
1505+char* circle_statement(){
1506+ return graphic_statement(FUNC_CIRCLE);
1507+}
1508+
1509+char* circlefill_statement(){
1510+ return graphic_statement(FUNC_CIRCLEFILL);
1511+}
1512+
1513+char* gprint_statement(){
1514+ return graphic_statement(FUNC_GPRINT);
1515+}
1516+
1517+char* putbmp_statement(){
1518+ return graphic_statement(FUNC_PUTBMP);
1519+}
1520+
1521+char* point_statement(){
1522+ return graphic_statement(FUNC_POINT);
1523+}
1524+
1525+char* fopen_statement(){
1526+ return fopen_statement_main(FUNC_FOPENST);
1527+}
1528+
1529+char* fprint_statement(){
1530+ return print_statement_main(LIB_FILE | FUNC_FPRINTSTR,LIB_FILE | FUNC_FSTRING);
1531+}
1532+
1533+static const void* statement_list[]={
1534+ "REM",rem_statement,
1535+ "SOUND ",sound_statement,
1536+ "MUSIC ",music_statement,
1537+ "DRAWCOUNT ",drawcount_statement,
1538+ "CURSOR ",cursor_statement,
1539+ "PALETTE ",palette_statement,
1540+ "GPALETTE ",gpalette_statement,
1541+ "BGCOLOR ",bgcolor_statement,
1542+ "CLS",cls_statement,
1543+ "GCLS",gcls_statement,
1544+ "COLOR ",color_statement,
1545+ "GCOLOR ",gcolor_statement,
1546+ "RESTORE ",restore_statement,
1547+ "DATA ",data_statement,
1548+ "CDATA ",cdata_statement,
1549+ "LABEL ",label_statement,
1550+ "DIM ",dim_statement,
1551+ "CLEAR",clear_statement,
1552+ "PRINT",print_statement,
1553+ "IF ",if_statement,
1554+ "ELSEIF ",elseif_statement,
1555+ "ELSE",else_statement,
1556+ "ENDIF",endif_statement,
1557+ "END",end_statement,
1558+ "EXEC ",exec_statement,
1559+ "GOTO ",goto_statement,
1560+ "GOSUB ",gosub_statement,
1561+ "RETURN",return_statement,
1562+ "POKE ",poke_statement,
1563+ "FOR ",for_statement,
1564+ "NEXT",next_statement,
1565+ "LET ",let_statement,
1566+ "PCG ",pcg_statement,
1567+ "USEPCG",usepcg_statement,
1568+ "SCROLL ",scroll_statement,
1569+ "WAIT ",wait_statement,
1570+ "USEGRAPHIC",usegraphic_statement,
1571+ "PSET ",pset_statement,
1572+ "LINE ",line_statement,
1573+ "BOXFILL ",boxfill_statement,
1574+ "CIRCLE ",circle_statement,
1575+ "CIRCLEFILL ",circlefill_statement,
1576+ "GPRINT ",gprint_statement,
1577+ "PUTBMP ",putbmp_statement,
1578+ "POINT ",point_statement,
1579+ "VAR ",var_statement,
1580+ "DO",do_statement,
1581+ "LOOP",loop_statement,
1582+ "WHILE ",while_statement,
1583+ "WEND",wend_statement,
1584+ "BREAK",break_statement,
1585+ "CONTINUE",continue_statement,
1586+ "SYSTEM",system_statement,
1587+ "WIDTH ",width_statement,
1588+ "FOPEN ",fopen_statement,
1589+ "FILE ",file_statement,
1590+ "FCLOSE",fclose_statement,