• R/O
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

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


Commit MetaInfo

Revision148 (tree)
Time2016-08-05 03:35:13
Authorkmorimatsu

Log Message

MachiKania type Z ver 1.00

Change Summary

Incremental Difference

--- mips/tags/zoea1.00/editor.c (nonexistent)
+++ mips/tags/zoea1.00/editor.c (revision 148)
@@ -0,0 +1,1861 @@
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+
38+// カーソル関連位置の一時避難用
39+_tbuf *cursorbp_t;
40+unsigned short cursorix_t;
41+_tbuf *disptopbp_t;
42+unsigned short disptopix_t;
43+int cx_t,cy_t;
44+
45+//unsigned char clipboard[EDITWIDTHX*EDITWIDTHY]; //クリップボード、最大サイズは編集画面領域と同じ
46+unsigned char *clipboard; //実体は配列RAM[]の中に確保する
47+
48+int clipsize; //現在クリップボードに格納されている文字数
49+int edited; //保存後に変更されたかを表すフラグ
50+
51+//unsigned char filebuf[FILEBUFSIZE]; //ファイルアクセス用バッファ
52+unsigned char *filebuf; //実体は配列RAM[]の中に確保する
53+
54+unsigned char currentfile[13],tempfile[13]; //編集中のファイル名、一時ファイル名
55+
56+//unsigned char filenames[MAXFILENUM][13]; //ロード時のファイル名一覧バッファ
57+unsigned char (*filenames)[13]; //実体は配列RAM[]の中に確保する
58+
59+const unsigned char Message1[]="Hit Any Key\n";
60+const unsigned char Message2[]="File System Error\n";
61+const unsigned char Message3[]="Retry:[Enter] / Quit:[ESC]\n";
62+void wait60thsec(unsigned short n){
63+ // 60分のn秒ウェイト(ビデオ画面の最下行信号出力終了まで待つ)
64+ n+=drawcount;
65+ while(drawcount!=n) asm(WAIT);
66+}
67+
68+unsigned int bpixtopos(_tbuf *bp,unsigned int ix){
69+// テキストバッファ上の位置からテキスト全体の先頭から何文字目かを返す
70+// bp:テキストバッファポインタ
71+// ix:bp->Bufの先頭からの文字数
72+ unsigned int pos;
73+ _tbuf *sbp;
74+ pos=0;
75+ sbp=TBufstart;
76+ while(sbp!=bp){
77+ pos+=sbp->n;
78+ sbp=sbp->next;
79+ if(sbp==NULL) return 0; //エラー
80+ }
81+ return pos+ix;
82+}
83+_tbuf * postobpix(int pos,unsigned short *pix){
84+// テキスト全体の先頭からpos文字目のテキストバッファ上の位置を返す
85+// 戻り値 テキストバッファポインタ
86+// *pix(戻り値):戻り値テキストバッファの先頭からの位置(ポインタ渡し)
87+ _tbuf *bp;
88+ bp=TBufstart;
89+ while(pos >= bp->n){
90+ if(bp->next==NULL) break; //全体最後尾の場合
91+ pos-=bp->n;
92+ bp=bp->next;
93+ }
94+ if(pos > bp->n){
95+ // オーバーランエラーの場合先頭を返す
96+ *pix=0;
97+ return TBufstart;
98+ }
99+ *pix=pos;
100+ return bp;
101+}
102+_tbuf * linetobpix(int line,unsigned short *pix){
103+// テキスト全体の先頭からline行目のテキストバッファ上の位置を返す
104+// 戻り値 テキストバッファポインタ
105+// *pix(戻り値):戻り値テキストバッファの先頭からの位置(ポインタ渡し)
106+ _tbuf *bp,*bp2;
107+ int ix,ix2;
108+ bp=TBufstart;
109+ bp2=TBufstart;
110+ ix=0;
111+ ix2=0;
112+ while(line>1){
113+ while(1){
114+ if(ix>=bp->n){
115+ if(bp->next==NULL) break;
116+ bp=bp->next;
117+ ix=0;
118+ continue;
119+ }
120+ if(bp->Buf[ix++] == '\n'){
121+ bp2=bp;
122+ ix2=ix;
123+ break;
124+ }
125+ }
126+ line--;
127+ }
128+ *pix=ix2;
129+ return bp2;
130+}
131+
132+_tbuf * newTBuf(_tbuf *prev){
133+// 新しいテキストバッファ1行を生成
134+// prev:挿入先の行(prevの後ろに追加)
135+// 戻り値 生成したバッファへのポインタ、生成できない場合NULL
136+ _tbuf *bp,*next;
137+
138+ //バッファの先頭から空きをサーチ
139+ bp=TextBuffer;
140+ while(1){
141+ if(bp->prev==NULL && bp!=TBufstart) break;
142+ bp++;
143+ if(bp>=TextBuffer+TBUFMAXLINE) return NULL;//最後まで空きなし
144+ }
145+ next=prev->next;
146+ //行挿入
147+ bp->prev=prev;
148+ bp->next=next;
149+ prev->next=bp;
150+ if(next!=NULL) next->prev=bp;
151+ bp->n=0;
152+ return bp;
153+}
154+
155+_tbuf * deleteTBuf(_tbuf *bp){
156+// テキストバッファの削除
157+// bp:削除する行のポインタ
158+// 戻り値 削除前の次のバッファへのポインタ、ない場合NULL
159+ unsigned short a,b;
160+ _tbuf *prev,*next;
161+ prev=bp->prev;
162+ next=bp->next;
163+ if(prev==NULL){
164+ //先頭行の場合
165+ if(next==NULL) return next; //最後の1行の場合は削除しない
166+ TBufstart=next; //次の行を先頭行設定
167+ }
168+ else prev->next=next; //前を次にリンク(最終行ならNULLがコピーされる)
169+ if(next!=NULL) next->prev=prev; //次があれば次を前にリンク
170+ bp->prev=NULL; //空きフラグ設定
171+ return next;
172+}
173+
174+int insertchar(_tbuf *bp,unsigned int ix,unsigned char c){
175+//テキストバッファbpの先頭からixバイトの位置にcを挿入
176+//戻り値 成功:0、不正または容量オーバー:-1、空きがあるはずなのに失敗:1
177+ unsigned char *p;
178+
179+ if(ix > bp->n) return -1; //不正指定
180+ if(num >= TBUFMAXSIZE) return -1; //バッファ容量オーバー
181+ if(bp->n < TBUFSIZE){
182+ //ライン内だけで1バイト挿入可能//
183+ for(p=bp->Buf + bp->n ; p > bp->Buf+ix ; p--) *p=*(p-1);
184+ *p=c;
185+ bp->n++;
186+ num++; //バッファ使用量
187+// if(bp->n >= TBUFSIZE && bp->next==NULL) newTBuf(bp); //バッファがいっぱいになったら新たにバッファ生成
188+ return 0;
189+ }
190+ //ラインがあふれる場合
191+ if(bp->next==NULL || bp->next->n >=TBUFSIZE){
192+ // 最終行または次のラインバッファがいっぱいだったら一行挿入
193+ if(newTBuf(bp)==NULL){
194+ // ラインバッファ挿入不可
195+ return 1;
196+ }
197+ }
198+ if(ix==TBUFSIZE){
199+ insertchar(bp->next,0,c);
200+ return 0;
201+ }
202+ p=bp->Buf + TBUFSIZE-1;
203+ insertchar(bp->next,0,*p); //次の行の先頭に1文字挿入(必ず空きあり)
204+ for( ; p > bp->Buf+ix ; p--) *p=*(p-1);
205+ *p=c;
206+ return 0;
207+}
208+
209+int overwritechar(_tbuf *bp,unsigned int ix,unsigned char c){
210+//テキストバッファbpの先頭からixバイトの位置をcで上書き
211+//戻り値 成功:0、不正または容量オーバー:-1、空きがあるはずなのに失敗:1
212+
213+ //現在のバッファ位置の文字が終端または改行の場合、挿入モード
214+ if(ix > bp->n) return -1; //不正指定
215+ while(ix >= bp->n){
216+ if(bp->next==NULL){
217+ //テキスト全体最後尾の場合は挿入
218+ return insertchar(bp,ix,c);
219+ }
220+ bp=bp->next;
221+ ix=0;
222+ }
223+ if(bp->Buf[ix]=='\n') return insertchar(bp,ix,c);
224+ else bp->Buf[ix]=c;
225+ return 0;
226+}
227+
228+void deletechar(_tbuf *bp,unsigned int ix){
229+//テキストバッファbpの先頭からkバイトの位置の1バイト削除
230+ unsigned char *p;
231+
232+ if(ix > bp->n) return; //不正指定
233+ if(ix !=bp->n){
234+ //バッファの最後の文字より後ろでない場合
235+ for(p=bp->Buf+ix ; p< bp->Buf + bp->n-1 ; p++) *p=*(p+1);
236+ bp->n--;
237+ num--; //バッファ使用量
238+ return;
239+ }
240+ //行バッファの現在の最後の場合(削除する文字がない場合)
241+ if(bp->next==NULL) return; //全体の最後の場合、何もしない
242+ deletechar(bp->next,0); //次の行の先頭文字を削除
243+}
244+int gabagecollect1(void){
245+//断片化されたテキストバッファの隙間を埋めるガベージコレクション
246+//カーソルの前と後ろそれぞれ探索して最初の1バイト分のみ実施
247+//戻り値 1バイトでも移動した場合:1、なかった場合:0
248+
249+ _tbuf *bp;
250+ int f=0;
251+ unsigned char *p,*p2;
252+
253+ //カーソルがバッファの先頭にある場合、前のバッファの最後尾に変更
254+ //(ただし前に空きがない場合と先頭バッファの場合を除く)
255+ while(cursorix==0 && cursorbp->prev!=NULL && cursorbp->prev->n <TBUFSIZE){
256+ cursorbp=cursorbp->prev;
257+ cursorix=cursorbp->n;
258+ }
259+ //画面左上位置がバッファの先頭にある場合、前のバッファの最後尾に変更
260+ //(ただし先頭バッファの場合を除く)
261+ while(disptopix==0 && disptopbp->prev!=NULL){
262+ disptopbp=disptopbp->prev;
263+ disptopix=disptopbp->n;
264+ }
265+ //カーソルのあるバッファ以外の空バッファを全て削除
266+ bp=TBufstart;
267+ while(bp!=NULL){
268+ if(bp->n == 0 && bp!=cursorbp) bp=deleteTBuf(bp); //空きバッファ削除
269+ else bp=bp->next;
270+ }
271+
272+ //カーソル位置より前の埋まっていないバッファを先頭からサーチ
273+ bp=TBufstart;
274+ while(bp->n >= TBUFSIZE){
275+ if(bp==cursorbp) break;
276+ bp=bp->next;
277+ }
278+ if(bp!=cursorbp){
279+ //最初に見つけた空き場所に次のバッファから1バイト移動
280+ bp->Buf[bp->n++] = bp->next->Buf[0];
281+ bp=bp->next;
282+ p=bp->Buf;
283+ p2=p+bp->n-1;
284+ for( ; p<p2 ; p++) *p=*(p+1);
285+ bp->n--;
286+ f=1;
287+ if(bp == disptopbp) disptopix--;
288+ if(bp == cursorbp) cursorix--;
289+// else if(bp->n == 0) deleteTBuf(bp);
290+ }
291+ if(cursorbp->next ==NULL) return f; //カーソル位置が最終バッファなら終了
292+ //カーソル位置の次のバッファから埋まっていないバッファをサーチ
293+ bp=cursorbp;
294+ do{
295+ bp=bp->next;
296+ if(bp->next ==NULL) return f; //最終バッファに到達なら終了
297+ } while(bp->n >=TBUFSIZE);
298+
299+ //最初に見つけた空き場所に次のバッファから1バイト移動
300+ bp->Buf[bp->n++] = bp->next->Buf[0];
301+ bp=bp->next;
302+ p=bp->Buf;
303+ p2=p+bp->n-1;
304+ for( ; p<p2 ; p++) *p=*(p+1);
305+ bp->n--;
306+ f=1;
307+ if(bp->n == 0) deleteTBuf(bp);
308+ return f;
309+}
310+void gabagecollect2(void){
311+// 変化がなくなるまで1バイト分のガベージコレクションを呼び出し
312+ while(gabagecollect1()) ;
313+}
314+void inittextbuf(void){
315+// テキストバッファの初期化
316+ _tbuf *bp;
317+ for(bp=TextBuffer;bp<TextBuffer+TBUFMAXLINE;bp++) bp->prev=NULL; //未使用バッファ化
318+ TBufstart=TextBuffer; //リンクの先頭設定
319+ TBufstart->next=NULL;
320+ TBufstart->n=0;
321+ num=0; //バッファ使用量
322+ edited=0; //編集済みフラグクリア
323+}
324+void redraw(){
325+//画面の再描画
326+ unsigned char *vp;
327+ _tbuf *bp,*bp1,*bp2;
328+ int ix,ix1,ix2;
329+ int x,y;
330+ unsigned char ch,cl;
331+
332+ vp=TVRAM;
333+ bp=disptopbp;
334+ ix=disptopix;
335+ cl=COLOR_NORMALTEXT;
336+ if(cursorbp1==NULL){
337+ //範囲選択モードでない場合
338+ bp1=NULL;
339+ bp2=NULL;
340+ }
341+ else{
342+ //範囲選択モードの場合、開始位置と終了の前後判断して
343+ //bp1,ix1を開始位置、bp2,ix2を終了位置に設定
344+ if(cy<cy1 || (cy==cy1 && cx<cx1)){
345+ bp1=cursorbp;
346+ ix1=cursorix;
347+ bp2=cursorbp1;
348+ ix2=cursorix1;
349+ }
350+ else{
351+ bp1=cursorbp1;
352+ ix1=cursorix1;
353+ bp2=cursorbp;
354+ ix2=cursorix;
355+ }
356+ }
357+ for(y=0;y<EDITWIDTHY;y++){
358+ if(bp==NULL) break;
359+ for(x=0;x<EDITWIDTHX;x++){
360+ //文字がある位置までサーチ
361+ while(ix>=bp->n){
362+ if(bp==bp1 && ix==ix1) cl=COLOR_AREASELECTTEXT;
363+ if(bp==bp2 && ix==ix2) cl=COLOR_NORMALTEXT;
364+ bp=bp->next;
365+ ix=0;
366+ if(bp==NULL) break;
367+ }
368+ if(bp==NULL) break; //バッファ最終
369+ if(bp==bp1 && ix==ix1) cl=COLOR_AREASELECTTEXT;
370+ if(bp==bp2 && ix==ix2) cl=COLOR_NORMALTEXT;
371+ ch=bp->Buf[ix++];
372+ if(ch=='\n') break;
373+ *(vp+ATTROFFSET)=cl;
374+ *vp++=ch;
375+ }
376+ //改行およびバッファ最終以降の右側表示消去
377+ for(;x<EDITWIDTHX;x++){
378+ *(vp+ATTROFFSET)=0;
379+ *vp++=0;
380+ }
381+ }
382+ //バッファ最終以降の下側表示消去
383+ for(;y<EDITWIDTHY;y++){
384+ for(x=0;x<EDITWIDTHX;x++){
385+ *(vp+ATTROFFSET)=0;
386+ *vp++=0;
387+ }
388+ }
389+}
390+
391+void cursor_left(void){
392+//カーソルを1つ前に移動
393+//出力:下記変数を移動先の値に変更
394+//cursorbp,cursorix バッファ上のカーソル位置
395+//cx,cy 画面上のカーソル位置
396+//cx2 cxと同じ
397+//disptopbp,disptopix 画面左上のバッファ上の位置
398+
399+ _tbuf *bp;
400+ int ix;
401+ int i;
402+ int x;
403+
404+ //バッファ上のカーソル位置を1つ前に移動
405+ if(cursorix!=0) cursorix--;
406+ else while(1) {
407+ //1つ前のバッファの最後尾に移動、ただし空バッファは飛ばす
408+ if(cursorbp->prev==NULL) return; //テキスト全体先頭なので移動しない
409+ cursorbp=cursorbp->prev;
410+ if(cursorbp->n >0){
411+ cursorix=cursorbp->n-1;//バッファ最後尾
412+ break;
413+ }
414+ }
415+
416+ //カーソルおよび画面左上位置の更新
417+ if(cx>0){
418+ //左端でなければカーソルを単純に1つ左に移動して終了
419+ cx--;
420+ cx2=cx;
421+ return;
422+ }
423+ if(cy>0){
424+ //左端だが上端ではない場合
425+ if(cursorbp->Buf[cursorix]!='\n'){
426+ // 移動先が改行コードでない場合、カーソルは1つ上の行の右端に移動
427+ cx=EDITWIDTHX-1;
428+ cx2=cx;
429+ cy--;
430+ return;
431+ }
432+ //画面左上位置から最後尾のX座標をサーチ
433+ bp=disptopbp;
434+ ix=disptopix;
435+ x=0;
436+ while(ix!=cursorix || bp!=cursorbp){
437+ if(bp->n==0){
438+ //空バッファの場合次へ
439+ bp=bp->next;
440+ ix=0;
441+ continue;
442+ }
443+ if(bp->Buf[ix++]=='\n' || x>=EDITWIDTHX-1) x=0;
444+ else x++;
445+ if(ix >= bp->n){
446+ bp=bp->next;
447+ ix=0;
448+ }
449+ }
450+ cx=x;
451+ cx2=cx;
452+ cy--;
453+ return;
454+ }
455+
456+ //左端かつ上端の場合
457+ if(cursorbp->Buf[cursorix]!='\n'){
458+ // 移動先が改行コードでない場合、カーソルは右端に移動
459+ // 画面左上位置は画面横幅分前に移動
460+ cx=EDITWIDTHX-1;
461+ cx2=cx;
462+ }
463+ else{
464+ //移動先が改行コードの場合
465+ //行頭(改行の次の文字またはバッファ先頭)と現在位置の文字数差を
466+ //画面横幅で割った余りがカーソルX座標
467+ bp=cursorbp;
468+ ix=cursorix;
469+ i=0;
470+ while(1){
471+ if(ix==0){
472+ if(bp->prev==NULL) break;
473+ bp=bp->prev;
474+ ix=bp->n;
475+ continue;
476+ }
477+ ix--;
478+ if(bp->Buf[ix]=='\n') break;
479+ i++;
480+ }
481+ cx=i % EDITWIDTHX;
482+ cx2=cx;
483+ }
484+ //画面左上位置は現在位置からX座標分引いたところ
485+ bp=cursorbp;
486+ ix=cursorix;
487+ x=cx;
488+ while(x>0){
489+ if(ix==0){
490+ bp=bp->prev;
491+ ix=bp->n;
492+ continue;
493+ }
494+ ix--;
495+ x--;
496+ }
497+ disptopbp=bp;
498+ disptopix=ix;
499+}
500+void cursor_right(void){
501+//カーソルを1つ後ろに移動
502+//出力:下記変数を移動先の値に変更
503+//cursorbp,cursorix バッファ上のカーソル位置
504+//cx,cy 画面上のカーソル位置
505+//cx2 cxと同じ
506+//disptopbp,disptopix 画面左上のバッファ上の位置
507+
508+ _tbuf *bp;
509+ int ix;
510+ int i;
511+ int x;
512+ unsigned char c;
513+
514+ if(cursorix >= cursorbp->n){
515+ //バッファ最後尾の場合、次の先頭に移動
516+ bp=cursorbp;
517+ while(1) {
518+ //空バッファは飛ばす
519+ if(bp->next==NULL) return; //テキスト全体最後尾なので移動しない
520+ bp=bp->next;
521+ if(bp->n >0) break;
522+ }
523+ cursorbp=bp;
524+ cursorix=0;//バッファ先頭
525+ }
526+ c=cursorbp->Buf[cursorix++]; //バッファ上のカーソル位置のコードを読んで1つ後ろに移動
527+ if(c!='\n' && cx<EDITWIDTHX-1){
528+ //カーソル位置が改行でも右端でもない場合単純に1つ右に移動して終了
529+ cx++;
530+ cx2=cx;
531+ return;
532+ }
533+ cx=0; //カーソルを右端に移動
534+ cx2=cx;
535+ if(cy<EDITWIDTHY-1){
536+ //下端でなければカーソルを次行に移動して終了
537+ cy++;
538+ return;
539+ }
540+ //下端の場合
541+ //画面左上位置を更新
542+ //改行コードまたは画面横幅超えるまでサーチ
543+ bp=disptopbp;
544+ ix=disptopix;
545+ x=0;
546+ while(x<EDITWIDTHX){
547+ if(ix >= bp->n){
548+ bp=bp->next;
549+ ix=0;
550+ continue;
551+ }
552+ if(bp->Buf[ix++]=='\n') break;
553+ x++;
554+ }
555+ disptopbp=bp;
556+ disptopix=ix;
557+}
558+void cursor_up(void){
559+//カーソルを1つ上に移動
560+//出力:下記変数を移動先の値に変更
561+//cursorbp,cursorix バッファ上のカーソル位置
562+//cx,cy 画面上のカーソル位置
563+//cx2 移動前のcxと同じ
564+//disptopbp,disptopix 画面左上のバッファ上の位置
565+
566+ _tbuf *bp;
567+ int ix;
568+ int i;
569+ int x;
570+ unsigned char c;
571+
572+ //画面幅分前に戻ったところがバッファ上カーソルの移動先
573+ //途中で改行コードがあれば別の手段で検索
574+ bp=cursorbp;
575+ ix=cursorix;
576+ i=cx2-cx;
577+ while(i<EDITWIDTHX){
578+ if(ix==0){
579+ if(bp->prev==NULL) return; //バッファ先頭までサーチしたら移動なし
580+ bp=bp->prev;
581+ ix=bp->n;
582+ continue;
583+ }
584+ ix--;
585+ if(bp->Buf[ix]=='\n') break;
586+ i++;
587+ }
588+ cursorbp=bp;
589+ cursorix=ix;
590+ //画面幅の間に改行コードがなかった場合
591+ if(i==EDITWIDTHX){
592+ cx=cx2;
593+ //画面上端でなければカーソルを1つ上に移動して終了
594+ if(cy>0){
595+ cy--;
596+ return;
597+ }
598+ //画面上端の場合、カーソル位置からX座標分戻ったところが画面左上位置
599+ x=cx;
600+ while(x>0){
601+ if(ix==0){
602+ bp=bp->prev;
603+ ix=bp->n;
604+ continue;
605+ }
606+ ix--;
607+ x--;
608+ }
609+ disptopbp=bp;
610+ disptopix=ix;
611+ return;
612+ }
613+ //改行が見つかった場合
614+ //行頭(改行の次の文字またはバッファ先頭)と現在位置の文字数差を
615+ //画面横幅で割った余りを求める
616+ i=0;
617+ while(1){
618+ if(ix==0){
619+ if(bp->prev==NULL) break;
620+ bp=bp->prev;
621+ ix=bp->n;
622+ continue;
623+ }
624+ ix--;
625+ if(bp->Buf[ix]=='\n') break;
626+ i++;
627+ }
628+ x=i % EDITWIDTHX; //改行ブロックの最終行の右端
629+ bp=cursorbp;
630+ ix=cursorix;
631+ //バッファ上のカーソル位置は改行ブロックの最終行右端からカーソルX座標分戻る
632+ //最終行右端のほうが小さい場合、その場所をバッファ上のカーソル位置とする
633+ while(x>cx2){
634+ if(ix==0){
635+ bp=bp->prev;
636+ ix=bp->n;
637+ continue;
638+ }
639+ ix--;
640+ x--;
641+ }
642+ cursorbp=bp;
643+ cursorix=ix;
644+ cx=x; //cx2または改行ブロック最終行右端
645+ if(cy>0){
646+ //画面上端でなければカーソルを1つ上に移動して終了
647+ cy--;
648+ return;
649+ }
650+ //画面上端の場合
651+ //画面左上位置は現在位置からX座標分引いたところ
652+ while(x>0){
653+ if(ix==0){
654+ bp=bp->prev;
655+ ix=bp->n;
656+ continue;
657+ }
658+ ix--;
659+ x--;
660+ }
661+ disptopbp=bp;
662+ disptopix=ix;
663+}
664+void cursor_down(void){
665+//カーソルを1つ下に移動
666+//出力:下記変数を移動先の値に変更
667+//cursorbp,cursorix バッファ上のカーソル位置
668+//cx,cy 画面上のカーソル位置
669+//cx2 移動前のcxと同じ
670+//disptopbp,disptopix 画面左上のバッファ上の位置
671+
672+ _tbuf *bp;
673+ int ix;
674+ int x;
675+ unsigned char c;
676+
677+ //次行の先頭サーチ
678+ //カーソル位置から画面右端までの間に改行コードがあれば次の文字が先頭
679+ bp=cursorbp;
680+ ix=cursorix;
681+ x=cx;
682+ while(x<EDITWIDTHX){
683+ if(ix>=bp->n){
684+ if(bp->next==NULL) return; //バッファ最後までサーチしたら移動なし
685+ bp=bp->next;
686+ ix=0;
687+ continue;
688+ }
689+ c=bp->Buf[ix];
690+ ix++;
691+ x++;
692+ if(c=='\n') break;
693+ }
694+ //次行先頭からcx2文字数分後ろにサーチ
695+ x=0;
696+ while(x<cx2){
697+ if(ix>=bp->n){
698+ if(bp->next==NULL) break; //バッファ最後の場合そこに移動
699+ bp=bp->next;
700+ ix=0;
701+ continue;
702+ }
703+ if(bp->Buf[ix]=='\n') break; //改行コードの場合そこに移動
704+ ix++;
705+ x++;
706+ }
707+ cursorbp=bp;
708+ cursorix=ix;
709+ cx=x;
710+ //画面下端でなければカーソルを1つ下に移動して終了
711+ if(cy<EDITWIDTHY-1){
712+ cy++;
713+ return;
714+ }
715+ //下端の場合
716+ //画面左上位置を更新
717+ //改行コードまたは画面横幅超えるまでサーチ
718+ bp=disptopbp;
719+ ix=disptopix;
720+ x=0;
721+ while(x<EDITWIDTHX){
722+ if(ix >= bp->n){
723+ bp=bp->next;
724+ ix=0;
725+ continue;
726+ }
727+ if(bp->Buf[ix++]=='\n') break;
728+ x++;
729+ }
730+ disptopbp=bp;
731+ disptopix=ix;
732+}
733+void cursor_home(void){
734+//カーソルを行先頭に移動
735+//出力:下記変数を移動先の値に変更
736+//cursorbp,cursorix バッファ上のカーソル位置
737+//cx,cx2 0
738+//cy 変更なし
739+//disptopbp,disptopix 画面左上のバッファ上の位置(変更なし)
740+
741+ //カーソルX座標分前に移動
742+ while(cx>0){
743+ if(cursorix==0){
744+ //空バッファは飛ばす
745+ cursorbp=cursorbp->prev;
746+ cursorix=cursorbp->n;
747+ continue;
748+ }
749+ cursorix--;
750+ cx--;
751+ }
752+ cx2=0;
753+}
754+void cursor_end(void){
755+//カーソルを行末に移動
756+//出力:下記変数を移動先の値に変更
757+//cursorbp,cursorix バッファ上のカーソル位置
758+//cx,cx2 行末
759+//cy 変更なし
760+//disptopbp,disptopix 画面左上のバッファ上の位置(変更なし)
761+
762+ //カーソルX座標を画面幅分後ろに移動
763+ //改行コードまたはバッファ最終があればそこに移動
764+ while(cx<EDITWIDTHX-1){
765+ if(cursorix>=cursorbp->n){
766+ //空バッファは飛ばす
767+ if(cursorbp->next==NULL) break;
768+ cursorbp=cursorbp->next;
769+ cursorix=0;
770+ continue;
771+ }
772+ if(cursorbp->Buf[cursorix]=='\n') break;
773+ cursorix++;
774+ cx++;
775+ }
776+ cx2=cx;
777+}
778+void cursor_pageup(void){
779+//PageUpキー
780+//最上行が最下行になるまでスクロール
781+//出力:下記変数を移動先の値に変更
782+//cursorbp,cursorix バッファ上のカーソル位置
783+//cx,cx2
784+//cy
785+//disptopbp,disptopix 画面左上のバッファ上の位置
786+
787+ _tbuf *bp;
788+ int ix;
789+ int i;
790+ int cy_old;
791+
792+ cy_old=cy;
793+ while(cy>0) cursor_up(); // cy==0になるまでカーソルを上に移動
794+ for(i=0;i<EDITWIDTHY-1;i++){
795+ //画面行数-1行分カーソルを上に移動
796+ bp=disptopbp;
797+ ix=disptopix;
798+ cursor_up();
799+ if(bp==disptopbp && ix==disptopix) break; //最上行で移動できなかった場合抜ける
800+ }
801+ //元のY座標までカーソルを下に移動、1行も動かなかった場合は最上行に留まる
802+ if(i>0) while(cy<cy_old) cursor_down();
803+}
804+void cursor_pagedown(void){
805+//PageDownキー
806+//最下行が最上行になるまでスクロール
807+//出力:下記変数を移動先の値に変更
808+//cursorbp,cursorix バッファ上のカーソル位置
809+//cx,cx2
810+//cy
811+//disptopbp,disptopix 画面左上のバッファ上の位置
812+
813+ _tbuf *bp;
814+ int ix;
815+ int i;
816+ int y;
817+ int cy_old;
818+
819+ cy_old=cy;
820+ while(cy<EDITWIDTHY-1){
821+ // cy==EDITWIDTH-1になるまでカーソルを下に移動
822+ y=cy;
823+ cursor_down();
824+ if(y==cy) break;// バッファ最下行で移動できなかった場合抜ける
825+ }
826+ for(i=0;i<EDITWIDTHY-1;i++){
827+ //画面行数-1行分カーソルを下に移動
828+ bp=disptopbp;
829+ ix=disptopix;
830+ cursor_down();
831+ if(bp==disptopbp && ix==disptopix) break; //最下行で移動できなかった場合抜ける
832+ }
833+ //下端からさらに移動した行数分、カーソルを上に移動、1行も動かなかった場合は最下行に留まる
834+ if(i>0) while(cy>cy_old) cursor_up();
835+}
836+void cursor_top(void){
837+//カーソルをテキストバッファの先頭に移動
838+ cursorbp=TBufstart;
839+ cursorix=0;
840+ cursorbp1=NULL; //範囲選択モード解除
841+ disptopbp=cursorbp;
842+ disptopix=cursorix;
843+ cx=0;
844+ cx2=0;
845+ cy=0;
846+}
847+
848+int countarea(void){
849+//テキストバッファの指定範囲の文字数をカウント
850+//範囲は(cursorbp,cursorix)と(cursorbp1,cursorix1)で指定
851+//後ろ側の一つ前の文字までをカウント
852+ _tbuf *bp1,*bp2;
853+ int ix1,ix2;
854+ int n;
855+
856+ //範囲選択モードの場合、開始位置と終了の前後判断して
857+ //bp1,ix1を開始位置、bp2,ix2を終了位置に設定
858+ if(cy<cy1 || (cy==cy1 && cx<cx1)){
859+ bp1=cursorbp;
860+ ix1=cursorix;
861+ bp2=cursorbp1;
862+ ix2=cursorix1;
863+ }
864+ else{
865+ bp1=cursorbp1;
866+ ix1=cursorix1;
867+ bp2=cursorbp;
868+ ix2=cursorix;
869+ }
870+ n=0;
871+ while(1){
872+ if(bp1==bp2 && ix1==ix2) return n;
873+ if(ix1 < bp1->n){
874+ n++;
875+ ix1++;
876+ }
877+ else{
878+ bp1=bp1->next;
879+ ix1=0;
880+ }
881+ }
882+}
883+void deletearea(void){
884+//テキストバッファの指定範囲を削除
885+//範囲は(cursorbp,cursorix)と(cursorbp1,cursorix1)で指定
886+//後ろ側の一つ前の文字までを削除
887+//削除後のカーソル位置は選択範囲の先頭にし、範囲選択モード解除する
888+
889+ _tbuf *bp;
890+ int ix;
891+ int n;
892+
893+ n=countarea(); //選択範囲の文字数カウント
894+
895+ //範囲選択の開始位置と終了位置の前後を判断してカーソルを開始位置に設定
896+ if(cy>cy1 || (cy==cy1 && cx>cx1)){
897+ cursorbp=cursorbp1;
898+ cursorix=cursorix1;
899+ cx=cx1;
900+ cy=cy1;
901+ }
902+ cx2=cx;
903+ cursorbp1=NULL; //範囲選択モード解除
904+
905+ //bp,ixを開始位置に設定
906+ bp=cursorbp;
907+ ix=cursorix;
908+
909+ //選択範囲が最初のバッファの最後まである場合
910+ if(n>=(bp->n - ix)){
911+ n -= bp->n - ix; //削除文字数減
912+ num-=bp->n - ix; //バッファ使用量を減数
913+ bp->n=ix; //ix以降を削除
914+ bp=bp->next;
915+ if(bp==NULL) return;
916+ ix=0;
917+ }
918+ //次のバッファ以降、選択範囲の終了位置が含まれないバッファは削除
919+ while(n>=bp->n){
920+ n-=bp->n; //削除文字数減
921+ num-=bp->n; //バッファ使用量を減数
922+ bp=deleteTBuf(bp); //バッファ削除して次のバッファに進む
923+ if(bp==NULL) return;
924+ }
925+ //選択範囲の終了位置を含む場合、1文字ずつ削除
926+ while(n>0){
927+ deletechar(bp,ix); //バッファから1文字削除(numは関数内で1減される)
928+ n--;
929+ }
930+}
931+void clipcopy(void){
932+// 選択範囲をクリップボードにコピー
933+ _tbuf *bp1,*bp2;
934+ int ix1,ix2;
935+ char *ps,*pd;
936+
937+ //範囲選択モードの場合、開始位置と終了の前後判断して
938+ //bp1,ix1を開始位置、bp2,ix2を終了位置に設定
939+ if(cy<cy1 || (cy==cy1 && cx<cx1)){
940+ bp1=cursorbp;
941+ ix1=cursorix;
942+ bp2=cursorbp1;
943+ ix2=cursorix1;
944+ }
945+ else{
946+ bp1=cursorbp1;
947+ ix1=cursorix1;
948+ bp2=cursorbp;
949+ ix2=cursorix;
950+ }
951+ ps=bp1->Buf+ix1;
952+ pd=clipboard;
953+ clipsize=0;
954+ while(bp1!=bp2 || ix1!=ix2){
955+ if(ix1 < bp1->n){
956+ *pd++=*ps++;
957+ clipsize++;
958+ ix1++;
959+ }
960+ else{
961+ bp1=bp1->next;
962+ ps=bp1->Buf;
963+ ix1=0;
964+ }
965+ }
966+}
967+void clippaste(void){
968+// クリップボードから貼り付け
969+ int n,i;
970+ unsigned char *p;
971+
972+ p=clipboard;
973+ for(n=clipsize;n>0;n--){
974+ i=insertchar(cursorbp,cursorix,*p);
975+ if(i>0){
976+ //バッファ空きがあるのに挿入失敗の場合
977+ gabagecollect2(); //全体ガベージコレクション
978+ i=insertchar(cursorbp,cursorix,*p);//テキストバッファに1文字挿入
979+ }
980+ if(i!=0) return;//挿入失敗
981+ cursor_right();//画面上、バッファ上のカーソル位置を1つ後ろに移動
982+ p++;
983+ }
984+}
985+void set_areamode(){
986+//範囲選択モード開始時のカーソル開始位置グローバル変数設定
987+ cursorbp1=cursorbp;
988+ cursorix1=cursorix;
989+ cx1=cx;
990+ cy1=cy;
991+}
992+void save_cursor(void){
993+//カーソル関連グローバル変数を一時避難
994+ cursorbp_t=cursorbp;
995+ cursorix_t=cursorix;
996+ disptopbp_t=disptopbp;
997+ disptopix_t=disptopix;
998+ cx_t=cx;
999+ cy_t=cy;
1000+}
1001+void restore_cursor(void){
1002+//カーソル関連グローバル変数を一時避難場所から戻す
1003+ cursorbp=cursorbp_t;
1004+ cursorix=cursorix_t;
1005+ disptopbp=disptopbp_t;
1006+ disptopix=disptopix_t;
1007+ cx=cx_t;
1008+ cy=cy_t;
1009+}
1010+
1011+int filesystemretry(){
1012+// SDファイルシステムの再初期化確認と実施
1013+// SDファイルへの保存や読み込み時にファイルエラーが発生した場合に呼び出す
1014+// 戻り値 0:初期化成功、-1:成功することなくEscapeで抜けた
1015+ unsigned short vk;
1016+ while(1){
1017+ setcursorcolor(COLOR_NORMALTEXT);
1018+ printstr((unsigned char *)Message3); //Retry / Quit
1019+ while(1){
1020+ inputchar(); //1文字入力待ち
1021+ vk=vkey & 0xff;
1022+ if(vk==VK_RETURN || vk==VK_SEPARATOR) break;
1023+ if(vk==VK_ESCAPE) return -1;
1024+ }
1025+ //ファイルシステム初期化
1026+ if(FSInit()!=FALSE) return 0; //成功
1027+ //エラーの場合
1028+ setcursorcolor(COLOR_ERRORTEXT);
1029+ printstr((unsigned char *)Message2);//File System Error
1030+ }
1031+}
1032+
1033+int sdfilecopy(char *sourcefile,char *distfile){
1034+// SDカード上のファイルをコピー
1035+// soucefile:コピー元ファイル名
1036+// distfile:コピー先ファイル名
1037+// 戻り値:正常終了 0、エラー終了時エラー番号
1038+ FSFILE *sfp,*dfp;
1039+ int n,er,c;
1040+ er=0;
1041+ sfp=FSfopen(sourcefile,"r");
1042+ if(sfp==NULL) return ERR_CANTFILEOPEN;
1043+ dfp=FSfopen(distfile,"w");
1044+ if(dfp==NULL){
1045+ FSfclose(sfp);
1046+ return ERR_CANTFILEOPEN;
1047+ }
1048+ c=0;
1049+ while(1){
1050+ if(c==0){
1051+ printchar('.');
1052+ c=100;
1053+ }
1054+ c--;
1055+ n=FSfread(filebuf,1,FILEBUFSIZE,sfp);
1056+ if(n==0) break;
1057+ if(FSfwrite(filebuf,1,n,dfp)!=n){
1058+ er=ERR_CANTWRITEFILE;
1059+ break;
1060+ }
1061+ }
1062+ FSfclose(sfp);
1063+ FSfclose(dfp);
1064+ return er;
1065+}
1066+int savetextfile(char *filename){
1067+// テキストバッファをテキストファイルに書き込み
1068+// 書き込み成功で0、失敗でエラーコード(負数)を返す
1069+ FSFILE *fp;
1070+ _tbuf *bp;
1071+ int ix,n,i,er;
1072+ unsigned char *ps,*pd;
1073+ er=0;//エラーコード
1074+ i=-1;
1075+ fp=FSfopen(filename,"w");
1076+ if(fp==NULL) return ERR_CANTFILEOPEN;
1077+ bp=TBufstart;
1078+ ix=0;
1079+ ps=bp->Buf;
1080+ do{
1081+ pd=filebuf;
1082+ n=0;
1083+ while(n<FILEBUFSIZE-1){
1084+ //改行コードが2バイトになることを考慮してバッファサイズ-1までとする
1085+ while(ix>=bp->n){
1086+ bp=bp->next;
1087+ if(bp==NULL){
1088+ break;
1089+ }
1090+ ix=0;
1091+ ps=bp->Buf;
1092+ }
1093+ if(bp==NULL) break;
1094+ if(*ps=='\n'){
1095+ *pd++='\r'; //改行コード0A→0D 0Aにする
1096+ n++;
1097+ }
1098+ *pd++=*ps++;
1099+ ix++;
1100+ n++;
1101+ }
1102+ if(n>0){
1103+ i=FSfwrite(filebuf,1,n,fp);
1104+ if(i!=n) er=ERR_CANTWRITEFILE;
1105+ }
1106+ } while(bp!=NULL && er==0);
1107+ FSfclose(fp);
1108+ return er;
1109+}
1110+int loadtextfile(char *filename){
1111+// テキストファイルをテキストバッファに読み込み
1112+// 読み込み成功で0、失敗でエラーコード(負数)を返す
1113+ FSFILE *fp;
1114+ _tbuf *bp;
1115+ int ix,n,i,er;
1116+ unsigned char *ps,*pd;
1117+ er=0;//エラーコード
1118+ fp=FSfopen(filename,"r");
1119+ if(fp==NULL) return ERR_CANTFILEOPEN;
1120+ inittextbuf();
1121+ bp=TextBuffer;
1122+ ix=0;
1123+ pd=bp->Buf;
1124+ do{
1125+ n=FSfread(filebuf,1,FILEBUFSIZE,fp);
1126+ ps=filebuf;
1127+ for(i=0;i<n;i++){
1128+ if(ix>=TBUFSIZE){
1129+ bp->n=TBUFSIZE;
1130+ bp=newTBuf(bp);
1131+ if(bp==NULL){
1132+ er=ERR_FILETOOBIG;
1133+ break;
1134+ }
1135+ ix=0;
1136+ pd=bp->Buf;
1137+ }
1138+ if(*ps=='\r') ps++; //改行コード0D 0A→0Aにする(単純に0D無視)
1139+ else{
1140+ *pd++=*ps++;
1141+ ix++;
1142+ num++;//バッファ総文字数
1143+ if(num>TBUFMAXSIZE){
1144+ er=ERR_FILETOOBIG;
1145+ break;
1146+ }
1147+ }
1148+ }
1149+ } while(n==FILEBUFSIZE && er==0);
1150+ if(bp!=NULL) bp->n=ix;//最後のバッファの文字数
1151+ FSfclose(fp);
1152+ if(er) inittextbuf();//エラー発生の場合バッファクリア
1153+ return er;
1154+}
1155+int overwritecheck(char *fn){
1156+// ファイルの上書き確認
1157+// ファイルの存在をチェックし、存在する場合キーボードから上書き確認する
1158+// fn:ファイル名へのポインタ
1159+// 戻り値 0:存在しないまたは上書き、-1:上書きしない
1160+ SearchRec sr;
1161+ unsigned short vk;
1162+ if(FindFirst(tempfile,ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_ARCHIVE,&sr)) return 0; //ファイルが存在しない
1163+ setcursorcolor(COLOR_ERRORTEXT);
1164+ printstr(tempfile);
1165+ printstr(": File Exists\n");
1166+ setcursorcolor(COLOR_NORMALTEXT);
1167+ printstr("Ovewrite:[Enter] / Stop:[ESC]\n");
1168+ while(1){
1169+ inputchar(); //1文字入力待ち
1170+ vk=vkey & 0xff;
1171+ if(vk==VK_RETURN || vk==VK_SEPARATOR) return 0;
1172+ if(vk==VK_ESCAPE) return -1;
1173+ }
1174+}
1175+void save_as(int ow){
1176+// 現在のテキストバッファの内容をSDカードに保存
1177+// ow 0:名前を付けて保存  1:上書き保存
1178+// ファイル名はグローバル変数currentfile[]
1179+// ファイル名はキーボードから変更可能
1180+// 成功した場合currentfileを更新
1181+
1182+ int er;
1183+ unsigned char *ps,*pd;
1184+
1185+ cls();
1186+ setcursor(0,0,COLOR_NORMALTEXT);
1187+ printstr("Save To SD Card\n");
1188+ if(currentfile[0]==0) ow=0; //ファイル名が設定されていない場合名前を付けて保存
1189+
1190+ //currentfileからtempfileにコピー
1191+ ps=currentfile;
1192+ pd=tempfile;
1193+ while(*ps!=0) *pd++=*ps++;
1194+ *pd=0;
1195+
1196+ while(1){
1197+ if(ow==0){
1198+ printstr("File Name + [Enter] / [ESC]\n");
1199+ if(lineinput(tempfile,8+1+3)<0) return; //ESCキーが押された
1200+ if(tempfile[0]==0) continue; //NULL文字列の場合
1201+ if(overwritecheck(tempfile)) continue;
1202+ }
1203+ printstr("Writing...\n");
1204+ er=savetextfile(tempfile); //ファイル保存、er:エラーコード
1205+ if(er==0){
1206+ printstr("OK");
1207+ FSremove(TEMPFILENAME); //実行時に生成する一時ファイルを削除
1208+ //tempfileからcurrentfileにコピーして終了
1209+ ps=tempfile;
1210+ pd=currentfile;
1211+ while(*ps!=0) *pd++=*ps++;
1212+ *pd=0;
1213+ edited=0; //編集済みフラグクリア
1214+ wait60thsec(60);//1秒待ち
1215+ return;
1216+ }
1217+ setcursorcolor(COLOR_ERRORTEXT);
1218+ if(er==ERR_CANTFILEOPEN) printstr("Bad File Name or File Error\n");
1219+ else printstr("Cannot Write\n");
1220+ if(filesystemretry()) return; //ファイルシステム再初期化、あきらめた場合はreturnする
1221+ }
1222+}
1223+
1224+void msra(void){
1225+// Make Self-Running Application (自己実行アプリケーションの作成)
1226+// 最初にソースファイルを名前を付けて保存
1227+// 次にBASICシステムのHEXファイルをソースファイル名の拡張子をHEXにした名前でコピー
1228+
1229+ int er;
1230+ unsigned char vk;
1231+ unsigned char *ps,*pd;
1232+ cls();
1233+ setcursor(0,0,COLOR_NORMALTEXT);
1234+ printstr("Make Self-Running Application\n\n");
1235+
1236+ //currentfileからtempfileにコピー
1237+ ps=currentfile;
1238+ pd=tempfile;
1239+ while(*ps!=0) *pd++=*ps++;
1240+ *pd=0;
1241+
1242+ while(1){
1243+ setcursorcolor(COLOR_NORMALTEXT);
1244+ printstr("Input File Name (xxx.BAS)\n");
1245+ if(lineinput(tempfile,8+1+3)<0) return; //ESCキーが押された
1246+ ps=tempfile;
1247+ while(*ps!='.' && *ps!=0) ps++;
1248+ if(ps+4>=tempfile+13 ||
1249+ *ps!='.' ||
1250+ (*(ps+1)!='b' && *(ps+1)!='B') ||
1251+ (*(ps+2)!='a' && *(ps+2)!='A') ||
1252+ (*(ps+3)!='s' && *(ps+3)!='S') ||
1253+ *(ps+4)!=0){
1254+ setcursorcolor(COLOR_ERRORTEXT);
1255+ printstr("File Name Must Be xxx.BAS\n");
1256+ continue;
1257+ }
1258+ if(overwritecheck(tempfile)) continue;
1259+ printstr("Writing BASIC File\n");
1260+ er=savetextfile(tempfile); //ファイル保存、er:エラーコード
1261+ if(er==0) break;
1262+ setcursorcolor(COLOR_ERRORTEXT);
1263+ if(er==ERR_CANTFILEOPEN) printstr("Bad File Name or File Error\n");
1264+ else printstr("Cannot Write\n");
1265+ if(filesystemretry()) return; //ファイルシステム再初期化、あきらめた場合はreturnする
1266+ }
1267+ printstr("OK\n\n");
1268+ FSremove(TEMPFILENAME); //実行時に生成する一時ファイルを削除
1269+ //tempfileからcurrentfileにコピーして終了
1270+ ps=tempfile;
1271+ pd=currentfile;
1272+ while(*ps!=0) *pd++=*ps++;
1273+ *pd=0;
1274+ edited=0; //編集済みフラグクリア
1275+ // 拡張子をHEXにしてBASICシステムファイルをコピー
1276+ *(ps-3)='H';
1277+ *(ps-2)='E';
1278+ *(ps-1)='X';
1279+ if(overwritecheck(tempfile)) return;
1280+ printstr("Copying\n");
1281+ printstr(HEXFILE);
1282+ printstr(" To ");
1283+ printstr(tempfile);
1284+ printstr("\nWait For A While");
1285+ er=sdfilecopy(HEXFILE,tempfile);
1286+ if(er==0){
1287+ printstr("\nDone");
1288+ wait60thsec(120);//2秒待ち
1289+ return;
1290+ }
1291+ setcursorcolor(COLOR_ERRORTEXT);
1292+ if(er==ERR_CANTFILEOPEN){
1293+ printstr(HEXFILE);
1294+ printstr(" Not Found\n");
1295+ }
1296+ else if(er==ERR_CANTWRITEFILE){
1297+ printstr("Write Error\n");
1298+ }
1299+ setcursorcolor(COLOR_NORMALTEXT);
1300+ printstr((unsigned char *)Message1);// Hit Any Key
1301+ inputchar(); //1文字入力待ち
1302+ return;
1303+}
1304+
1305+int selectfile(void){
1306+// SDカードからファイルを選択して読み込み
1307+// currenfile[]にファイル名を記憶
1308+// 対象ファイル拡張子 BASおよびTXT
1309+// 戻り値 0:読み込みを行った -1:読み込みなし
1310+ unsigned int filenum,top,f;
1311+ int er;
1312+ unsigned char *ps,*pd;
1313+ unsigned char x,y;
1314+ unsigned char vk;
1315+ SearchRec sr;
1316+
1317+ //ファイルの一覧をSDカードから読み出し
1318+ cls();
1319+ if(edited && num){
1320+ //最終保存後に編集済みの場合、保存の確認
1321+ setcursorcolor(COLOR_NORMALTEXT);
1322+ printstr("Save Program Before Load?\n");
1323+ printstr("Save:[Enter] / Not Save:[ESC]\n");
1324+ while(1){
1325+ inputchar(); //1文字キー入力待ち
1326+ vk=vkey & 0xff;
1327+ if(vk==VK_RETURN || vk==VK_SEPARATOR){
1328+ save_as(0); //名前を付けて保存
1329+ break;
1330+ }
1331+ else if(vk==VK_ESCAPE) break;
1332+ }
1333+ }
1334+ filenum=0;
1335+ while(1){
1336+ //拡張子 BASファイルのサーチ
1337+ if(FindFirst("*.BAS",ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_ARCHIVE,&sr)==0){
1338+ do{
1339+ //filenames[]にファイル名の一覧を読み込み
1340+ ps=sr.filename;
1341+ pd=filenames[filenum];
1342+ while(*ps!=0) *pd++=*ps++;
1343+ *pd=0;
1344+ filenum++;
1345+ }
1346+ while(!FindNext(&sr) && filenum<MAXFILENUM);
1347+ }
1348+ if(filenum>=MAXFILENUM) break;
1349+ //拡張子 TXTファイルのサーチ
1350+ if(FindFirst("*.TXT",ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_ARCHIVE,&sr)==0){
1351+ do{
1352+ //filenames[]にファイル名の一覧を読み込み
1353+ ps=sr.filename;
1354+ pd=filenames[filenum];
1355+ while(*ps!=0) *pd++=*ps++;
1356+ *pd=0;
1357+ filenum++;
1358+ }
1359+ while(!FindNext(&sr) && filenum<MAXFILENUM);
1360+ }
1361+ if(filenum>=MAXFILENUM) break;
1362+ //拡張子 INIファイルのサーチ
1363+ if(FindFirst("*.INI",ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_ARCHIVE,&sr)==0){
1364+ do{
1365+ //filenames[]にファイル名の一覧を読み込み
1366+ ps=sr.filename;
1367+ pd=filenames[filenum];
1368+ while(*ps!=0) *pd++=*ps++;
1369+ *pd=0;
1370+ filenum++;
1371+ }
1372+ while(!FindNext(&sr) && filenum<MAXFILENUM);
1373+ }
1374+ if(filenum>0) break;
1375+ setcursorcolor(COLOR_ERRORTEXT);
1376+ printstr(".BAS or .TXT File Not Found\n");
1377+ if(filesystemretry()) return; //ファイルシステム再初期化、あきらめた場合はreturnする
1378+ }
1379+
1380+ //ファイル一覧を画面に表示
1381+ cls();
1382+ setcursor(0,0,COLOR_NORMALTEXT);
1383+ printstr("Load: ");
1384+ setcursorcolor(4);
1385+ printstr("Select&[Enter] / [ESC]\n");
1386+ for(f=0;f<filenum;f++){
1387+ x=(f&1)*15+1;
1388+ y=f/2+1;
1389+ if(y>=WIDTH_Y-1) break;
1390+ setcursor(x,y,COLOR_NORMALTEXT);
1391+ printstr(filenames[f]);
1392+ }
1393+
1394+ //ファイルの選択
1395+ top=0;//画面一番先頭のファイル番号
1396+ f=0;//現在選択中のファイル番号
1397+ setcursor(0,1,5);
1398+ printchar(0x1c); // Right Arrow
1399+ cursor--;
1400+ while(1){
1401+ inputchar();
1402+ vk=vkey & 0xff;
1403+ if(vk==0) continue;
1404+ printchar(' ');
1405+ setcursor(0,WIDTH_Y-1,COLOR_NORMALTEXT);
1406+ for(x=0;x<WIDTH_X-1;x++) printchar(' '); //最下行のステータス表示を消去
1407+ switch(vk){
1408+ case VK_UP:
1409+ case VK_NUMPAD8:
1410+ //上矢印キー
1411+ if(f>=2){
1412+ f-=2;
1413+ if(f<top){
1414+ //画面最上部の場合、下にスクロールして最上部にファイル名2つ表示
1415+ setcursor(WIDTH_X-1,WIDTH_Y-2,COLOR_NORMALTEXT);
1416+ while(cursor>=TVRAM+WIDTH_X*2){
1417+ *cursor=*(cursor-WIDTH_X);
1418+ *(cursor+ATTROFFSET)=*(cursor+ATTROFFSET-WIDTH_X);
1419+ cursor--;
1420+ }
1421+ while(cursor>=TVRAM+WIDTH_X) *cursor--=' ';
1422+ top-=2;
1423+ setcursor(1,1,COLOR_NORMALTEXT);
1424+ printstr(filenames[top]);
1425+ setcursor(16,1,COLOR_NORMALTEXT);
1426+ printstr(filenames[top+1]);
1427+ }
1428+ }
1429+ break;
1430+ case VK_DOWN:
1431+ case VK_NUMPAD2:
1432+ //下矢印キー
1433+ if(f+2<filenum){
1434+ f+=2;
1435+ if(f-top>=(WIDTH_Y-2)*2){
1436+ //画面最下部の場合、上にスクロールして最下部にファイル名1つor2つ表示
1437+ setcursor(0,1,COLOR_NORMALTEXT);
1438+ while(cursor<TVRAM+WIDTH_X*(WIDTH_Y-2)){
1439+ *cursor=*(cursor+WIDTH_X);
1440+ *(cursor+ATTROFFSET)=*(cursor+ATTROFFSET+WIDTH_X);
1441+ cursor++;
1442+ }
1443+ while(cursor<TVRAM+WIDTH_X*(WIDTH_Y-1)) *cursor++=' ';
1444+ top+=2;
1445+ setcursor(1,WIDTH_Y-2,COLOR_NORMALTEXT);
1446+ printstr(filenames[f&0xfffe]);
1447+ if((f|1)<filenum){
1448+ setcursor(16,WIDTH_Y-2,COLOR_NORMALTEXT);
1449+ printstr(filenames[f|1]);
1450+ }
1451+ }
1452+ }
1453+ break;
1454+ case VK_LEFT:
1455+ case VK_NUMPAD4:
1456+ //左矢印キー
1457+ if(f&1) f--;
1458+ break;
1459+ case VK_RIGHT:
1460+ case VK_NUMPAD6:
1461+ //右矢印キー
1462+ if((f&1)==0 && f+1<filenum) f++;
1463+ break;
1464+ case VK_RETURN: //Enterキー
1465+ case VK_SEPARATOR: //テンキーのEnter
1466+ //ファイル名決定。読み込んで終了
1467+ er=loadtextfile(filenames[f]); //テキストバッファにファイル読み込み
1468+ if(er==0){
1469+ //currenfile[]変数にファイル名をコピーして終了
1470+ ps=filenames[f];
1471+ pd=currentfile;
1472+ while(*ps!=0) *pd++=*ps++;
1473+ *pd=0;
1474+ return 0;
1475+ }
1476+ setcursor(0,WIDTH_Y-1,COLOR_ERRORTEXT);
1477+ if(er==ERR_CANTFILEOPEN) printstr("Cannot Open File");
1478+ else if(er=ERR_FILETOOBIG) printstr("File Too Big");
1479+ break;
1480+ case VK_ESCAPE:
1481+ //ESCキー、ファイル読み込みせず終了
1482+ return -1;
1483+ }
1484+ setcursor((f&1)*15,(f-top)/2+1,5);
1485+ printchar(0x1c);// Right Arrow
1486+ cursor--;
1487+ }
1488+}
1489+void newtext(void){
1490+// 新規テキスト作成
1491+ unsigned char vk;
1492+ if(edited && num){
1493+ //最終保存後に編集済みの場合、保存の確認
1494+ cls();
1495+ setcursorcolor(COLOR_NORMALTEXT);
1496+ printstr("Save Editing File?\n");
1497+ printstr("Save:[Enter] / Not Save:[ESC]\n");
1498+ while(1){
1499+ inputchar(); //1文字キー入力待ち
1500+ vk=vkey & 0xff;
1501+ if(vk==VK_RETURN || vk==VK_SEPARATOR){
1502+ save_as(0); //名前を付けて保存
1503+ break;
1504+ }
1505+ else if(vk==VK_ESCAPE) break;
1506+ }
1507+ }
1508+ inittextbuf(); //テキストバッファ初期化
1509+ cursor_top(); //カーソルをテキストバッファの先頭に設定
1510+ currentfile[0]=0; //作業中ファイル名クリア
1511+}
1512+void run(int test){
1513+//KM-BASICコンパイル&実行
1514+// test 0:コンパイルと実行、0以外:コンパイルのみで終了
1515+ int er,er2;
1516+ unsigned char vk;
1517+ unsigned int disptoppos,cursorpos;
1518+ int i,edited1;
1519+ _tbuf *bp;
1520+ unsigned short ix;
1521+
1522+ cls();
1523+ setcursor(0,0,COLOR_NORMALTEXT);
1524+ while(1){
1525+ er=savetextfile(TEMPFILENAME); //一時ファイルに保存、er:エラーコード
1526+ if(er==0) break;
1527+ setcursorcolor(COLOR_ERRORTEXT);
1528+ printstr("Cannot Write To SD Card\n");
1529+ if(filesystemretry()) return; //ファイルシステム再初期化、あきらめた場合はreturnする
1530+ }
1531+
1532+ //カーソル位置、画面表示位置の保存
1533+ disptoppos=bpixtopos(disptopbp,disptopix);
1534+ cursorpos=bpixtopos(cursorbp,cursorix);
1535+ edited1=edited; //編集済みフラグの一時退避
1536+ // Enable Break key
1537+ g_disable_break=0;
1538+ //KM-BASIC実行
1539+ er2=runbasic(TEMPFILENAME,test);
1540+
1541+ stopPCG();//システムフォントに戻す
1542+ setcursorcolor(COLOR_NORMALTEXT);
1543+ printchar('\n');
1544+ printstr((unsigned char *)Message1);// Hit Any Key
1545+ do ps2readkey(); //キーバッファが空になるまで読み出し
1546+ while(vkey!=0);
1547+ ps2mode(); //キーボード有効化
1548+ inputchar(); //1文字入力待ち
1549+ init_composite(); //パレット初期化のため画面初期化
1550+ while(1){
1551+ er=loadtextfile(TEMPFILENAME); //一時ファイルから戻す
1552+ if(er==0) break;
1553+ setcursorcolor(COLOR_ERRORTEXT);
1554+ printstr("Cannot Load From SD Card\n");
1555+ filesystemretry(); //ファイルシステム再初期化
1556+ }
1557+ if(er2<=0){
1558+ //正常終了またはファイルエラーまたはリンクエラーの場合
1559+ //カーソルを元の位置に設定
1560+ disptopbp=postobpix(disptoppos,&disptopix);
1561+ cursorbp=postobpix(cursorpos,&cursorix);
1562+ }
1563+ else{
1564+ //コンパイルエラーの場合
1565+ //カーソルをエラー行で画面トップに移動
1566+ disptopbp=linetobpix(er2,&disptopix);
1567+ cursorbp=disptopbp;
1568+ cursorix=disptopix;
1569+ cx=0;
1570+ cx2=0;
1571+ cy=0;
1572+ //中央になるようスクロール
1573+ for(i=0;i<EDITWIDTHY/2;i++){
1574+ //画面行数半分カーソルを上に移動
1575+ bp=disptopbp;
1576+ ix=disptopix;
1577+ cursor_up();
1578+ if(bp==disptopbp && ix==disptopix) break; //最上行で移動できなかった場合抜ける
1579+ }
1580+ for(;i>0;i--) cursor_down(); //元のY座標までカーソルを下に移動
1581+ }
1582+ cursorbp1=NULL; //範囲選択モード解除
1583+ clipsize=0; //クリップボードクリア
1584+ edited=edited1;
1585+ FSremove(TEMPFILENAME); //一時ファイル削除
1586+}
1587+void displaybottomline(void){
1588+//エディター画面最下行の表示
1589+ unsigned char *p;
1590+ unsigned char c;
1591+ p=cursor; //カーソル位置の退避
1592+ c=cursorcolor;
1593+ setcursor(0,WIDTH_Y-1,COLOR_BOTTOMLINE);
1594+ if(shiftkeys() & CHK_SHIFT)
1595+ printstr("NEW |MSRA| |TEST| ");
1596+ else
1597+ printstr("LOAD|SAVE| |RUN | ");
1598+ setcursorcolor(COLOR_ERRORTEXT);
1599+ printnum2(TBUFMAXSIZE-num,5);
1600+ cursor=p; //カーソル位置戻し
1601+ cursorcolor=c;
1602+}
1603+void normal_code_process(unsigned char k){
1604+// 通常文字入力処理
1605+// k:入力された文字コード
1606+ int i;
1607+
1608+ edited=1; //編集済みフラグ
1609+ if(insertmode || k=='\n' || cursorbp1!=NULL){ //挿入モード
1610+ if(cursorbp1!=NULL) deletearea();//選択範囲を削除
1611+ i=insertchar(cursorbp,cursorix,k);//テキストバッファに1文字挿入
1612+ if(i>0){
1613+ //バッファ空きがあるのに挿入失敗の場合
1614+ gabagecollect2(); //全体ガベージコレクション
1615+ i=insertchar(cursorbp,cursorix,k);//テキストバッファに1文字挿入
1616+ }
1617+ if(i==0) cursor_right();//画面上、バッファ上のカーソル位置を1つ後ろに移動
1618+ }
1619+ else{ //上書きモード
1620+ i=overwritechar(cursorbp,cursorix,k);//テキストバッファに1文字上書き
1621+ if(i>0){
1622+ //バッファ空きがあるのに上書き(挿入)失敗の場合
1623+ //(行末やバッファ最後尾では挿入)
1624+ gabagecollect2(); //全体ガベージコレクション
1625+ i=overwritechar(cursorbp,cursorix,k);//テキストバッファに1文字上書き
1626+ }
1627+ if(i==0) cursor_right();//画面上、バッファ上のカーソル位置を1つ後ろに移動
1628+ }
1629+}
1630+void control_code_process(unsigned char k,unsigned char sh){
1631+// 制御文字入力処理
1632+// k:制御文字の仮想キーコード
1633+// sh:シフト関連キー状態
1634+
1635+ save_cursor(); //カーソル関連変数退避(カーソル移動できなかった場合戻すため)
1636+ switch(k){
1637+ case VK_LEFT:
1638+ case VK_NUMPAD4:
1639+ //シフトキー押下していなければ範囲選択モード解除(NumLock+シフト+テンキーでも解除)
1640+ if((sh & CHK_SHIFT)==0 || (k==VK_NUMPAD4) && (sh & CHK_NUMLK)) cursorbp1=NULL;
1641+ else if(cursorbp1==NULL) set_areamode(); //範囲選択モードでなければ範囲選択モード開始
1642+ if(sh & CHK_CTRL){
1643+ //CTRL+左矢印でHome
1644+ cursor_home();
1645+ break;
1646+ }
1647+ cursor_left();
1648+ if(cursorbp1!=NULL && (disptopbp!=disptopbp_t || disptopix!=disptopix_t)){
1649+ //範囲選択モードで画面スクロールがあった場合
1650+ if(cy1<EDITWIDTHY-1) cy1++; //範囲スタート位置もスクロール
1651+ else restore_cursor(); //カーソル位置を戻す(画面範囲外の範囲選択禁止)
1652+ }
1653+ break;
1654+ case VK_RIGHT:
1655+ case VK_NUMPAD6:
1656+ //シフトキー押下していなければ範囲選択モード解除(NumLock+シフト+テンキーでも解除)
1657+ if((sh & CHK_SHIFT)==0 || (k==VK_NUMPAD6) && (sh & CHK_NUMLK)) cursorbp1=NULL;
1658+ else if(cursorbp1==NULL) set_areamode(); //範囲選択モードでなければ範囲選択モード開始
1659+ if(sh & CHK_CTRL){
1660+ //CTRL+右矢印でEnd
1661+ cursor_end();
1662+ break;
1663+ }
1664+ cursor_right();
1665+ if(cursorbp1!=NULL && (disptopbp!=disptopbp_t || disptopix!=disptopix_t)){
1666+ //範囲選択モードで画面スクロールがあった場合
1667+ if(cy1>0) cy1--; //範囲スタート位置もスクロール
1668+ else restore_cursor(); //カーソル位置を戻す(画面範囲外の範囲選択禁止)
1669+ }
1670+ break;
1671+ case VK_UP:
1672+ case VK_NUMPAD8:
1673+ //シフトキー押下していなければ範囲選択モード解除(NumLock+シフト+テンキーでも解除)
1674+ if((sh & CHK_SHIFT)==0 || (k==VK_NUMPAD8) && (sh & CHK_NUMLK)) cursorbp1=NULL;
1675+ else if(cursorbp1==NULL) set_areamode(); //範囲選択モードでなければ範囲選択モード開始
1676+ cursor_up();
1677+ if(cursorbp1!=NULL && (disptopbp!=disptopbp_t || disptopix!=disptopix_t)){
1678+ //範囲選択モードで画面スクロールがあった場合
1679+ if(cy1<EDITWIDTHY-1) cy1++; //範囲スタート位置もスクロール
1680+ else restore_cursor(); //カーソル位置を戻す(画面範囲外の範囲選択禁止)
1681+ }
1682+ break;
1683+ case VK_DOWN:
1684+ case VK_NUMPAD2:
1685+ //シフトキー押下していなければ範囲選択モード解除(NumLock+シフト+テンキーでも解除)
1686+ if((sh & CHK_SHIFT)==0 || (k==VK_NUMPAD2) && (sh & CHK_NUMLK)) cursorbp1=NULL;
1687+ else if(cursorbp1==NULL) set_areamode(); //範囲選択モードでなければ範囲選択モード開始
1688+ cursor_down();
1689+ if(cursorbp1!=NULL && (disptopbp!=disptopbp_t || disptopix!=disptopix_t)){
1690+ //範囲選択モードで画面スクロールがあった場合
1691+ if(cy1>0) cy1--; //範囲スタート位置もスクロール
1692+ else restore_cursor(); //カーソル位置を戻す(画面範囲外の範囲選択禁止)
1693+ }
1694+ break;
1695+ case VK_HOME:
1696+ case VK_NUMPAD7:
1697+ //シフトキー押下していなければ範囲選択モード解除(NumLock+シフト+テンキーでも解除)
1698+ if((sh & CHK_SHIFT)==0 || (k==VK_NUMPAD7) && (sh & CHK_NUMLK)) cursorbp1=NULL;
1699+ else if(cursorbp1==NULL) set_areamode(); //範囲選択モードでなければ範囲選択モード開始
1700+ cursor_home();
1701+ break;
1702+ case VK_END:
1703+ case VK_NUMPAD1:
1704+ //シフトキー押下していなければ範囲選択モード解除(NumLock+シフト+テンキーでも解除)
1705+ if((sh & CHK_SHIFT)==0 || (k==VK_NUMPAD1) && (sh & CHK_NUMLK)) cursorbp1=NULL;
1706+ else if(cursorbp1==NULL) set_areamode(); //範囲選択モードでなければ範囲選択モード開始
1707+ cursor_end();
1708+ break;
1709+ case VK_PRIOR: // PageUpキー
1710+ case VK_NUMPAD9:
1711+ //シフト+PageUpは無効(NumLock+シフト+「9」除く)
1712+ if((sh & CHK_SHIFT) && ((k!=VK_NUMPAD9) || ((sh & CHK_NUMLK)==0))) break;
1713+ cursorbp1=NULL; //範囲選択モード解除
1714+ cursor_pageup();
1715+ break;
1716+ case VK_NEXT: // PageDownキー
1717+ case VK_NUMPAD3:
1718+ //シフト+PageDownは無効(NumLock+シフト+「3」除く)
1719+ if((sh & CHK_SHIFT) && ((k!=VK_NUMPAD3) || ((sh & CHK_NUMLK)==0))) break;
1720+ cursorbp1=NULL; //範囲選択モード解除
1721+ cursor_pagedown();
1722+ break;
1723+ case VK_DELETE: //Deleteキー
1724+ case VK_DECIMAL: //テンキーの「.」
1725+ edited=1; //編集済みフラグ
1726+ if(cursorbp1!=NULL) deletearea();//選択範囲を削除
1727+ else deletechar(cursorbp,cursorix);
1728+ break;
1729+ case VK_BACK: //BackSpaceキー
1730+ edited=1; //編集済みフラグ
1731+ if(cursorbp1!=NULL){
1732+ deletearea();//選択範囲を削除
1733+ break;
1734+ }
1735+ if(cursorix==0 && cursorbp->prev==NULL) break; //バッファ先頭では無視
1736+ cursor_left();
1737+ deletechar(cursorbp,cursorix);
1738+ break;
1739+ case VK_INSERT:
1740+ case VK_NUMPAD0:
1741+ insertmode^=1; //挿入モード、上書きモードを切り替え
1742+ break;
1743+ case 'C':
1744+ //CTRL+C、クリップボードにコピー
1745+ if(cursorbp1!=NULL && (sh & CHK_CTRL)) clipcopy();
1746+ break;
1747+ case 'X':
1748+ //CTRL+X、クリップボードに切り取り
1749+ if(cursorbp1!=NULL && (sh & CHK_CTRL)){
1750+ clipcopy();
1751+ deletearea(); //選択範囲の削除
1752+ edited=1; //編集済みフラグ
1753+ }
1754+ break;
1755+ case 'V':
1756+ //CTRL+V、クリップボードから貼り付け
1757+ if((sh & CHK_CTRL)==0) break;
1758+ if(clipsize==0) break;
1759+ edited=1; //編集済みフラグ
1760+ if(cursorbp1!=NULL){
1761+ //範囲選択している時は削除してから貼り付け
1762+ if(num-countarea()+clipsize<=TBUFMAXSIZE){ //バッファ空き容量チェック
1763+ deletearea();//選択範囲を削除
1764+ clippaste();//クリップボード貼り付け
1765+ }
1766+ }
1767+ else{
1768+ if(num+clipsize<=TBUFMAXSIZE){ //バッファ空き容量チェック
1769+ clippaste();//クリップボード貼り付け
1770+ }
1771+ }
1772+ break;
1773+ case 'S':
1774+ //CTRL+S、SDカードに保存
1775+ if(num==0) break;
1776+ if(sh & CHK_CTRL) save_as(1); //上書き保存
1777+ break;
1778+ case 'O':
1779+ //CTRL+O、ファイル読み込み
1780+ if(sh & CHK_CTRL){
1781+ if(selectfile()==0){ //ファイルを選択して読み込み
1782+ //読み込みを行った場合、カーソル位置を先頭に
1783+ cursor_top();
1784+ }
1785+ }
1786+ break;
1787+ case 'N':
1788+ //CTRL+N、新規作成
1789+ if(sh & CHK_CTRL) newtext();
1790+ break;
1791+ case VK_F1: //F1キー
1792+ if(sh & CHK_SHIFT) newtext();//SHIFT+F1キー 新規作成
1793+ else{
1794+ //ファイル読み込み
1795+ if(selectfile()==0){ //ファイルを選択して読み込み
1796+ //読み込みを行った場合、カーソル位置を先頭に
1797+ cursor_top();
1798+ }
1799+ }
1800+ break;
1801+ case VK_F2: //F2キー
1802+ if(num==0) break;
1803+ if(sh & CHK_SHIFT) msra(); //create direct running file
1804+ else save_as(0); //ファイル名を付けて保存
1805+ break;
1806+ case VK_F4: //F4キー
1807+ if(num==0) break;
1808+ if(sh & CHK_SHIFT) run(1); //コンパイルテスト
1809+ else run(0); //コンパイル&実行
1810+ break;
1811+ }
1812+}
1813+void texteditor(void){
1814+//テキストエディター本体
1815+ unsigned char k1,k2,k3,sh;
1816+
1817+ TextBuffer=(_tbuf *)RAM;
1818+ clipboard=(unsigned char *)TextBuffer+sizeof(_tbuf)*TBUFMAXLINE;
1819+ filebuf=clipboard+EDITWIDTHX*EDITWIDTHY;
1820+ filenames=(unsigned char (*)[])(filebuf+FILEBUFSIZE);
1821+
1822+ inittextbuf(); //テキストバッファ初期化
1823+ currentfile[0]=0; //作業中ファイル名クリア
1824+
1825+ //実行時生成一時ファイルがあった場合は読み込む
1826+ if(loadtextfile(TEMPFILENAME)==0){
1827+ edited=1;
1828+ setcursorcolor(COLOR_ERRORTEXT);
1829+ printstr("Temporary File Loaded\n");
1830+ printstr("Save To SD Card If Necessary\n");
1831+ setcursorcolor(COLOR_NORMALTEXT);
1832+ printstr((unsigned char *)Message1); //Hit Any Key
1833+ inputchar(); //1文字入力待ち
1834+ }
1835+ cursor_top(); //カーソルをテキストバッファの先頭に移動
1836+ insertmode=1; //0:上書き、1:挿入
1837+ clipsize=0; //クリップボードクリア
1838+ blinktimer=0; //カーソル点滅タイマークリア
1839+
1840+ while(1){
1841+ redraw();//画面再描画
1842+ setcursor(cx,cy,COLOR_NORMALTEXT);
1843+ getcursorchar(); //カーソル位置の文字を退避(カーソル点滅用)
1844+ while(1){
1845+ //キー入力待ちループ
1846+ wait60thsec(1); //60分の1秒ウェイト
1847+ blinkcursorchar(); //カーソル点滅させる
1848+ k1=ps2readkey(); //キーバッファから読み込み、k1:通常文字入力の場合ASCIIコード
1849+ displaybottomline(); //画面最下行にファンクションキー機能表示
1850+ if(vkey) break; //キーが押された場合ループから抜ける
1851+ if(cursorbp1==NULL) gabagecollect1(); //1バイトガベージコレクション(範囲選択時はしない)
1852+ }
1853+ resetcursorchar(); //カーソルを元の文字表示に戻す
1854+ k2=(unsigned char)vkey; //k2:仮想キーコード
1855+ sh=vkey>>8; //sh:シフト関連キー状態
1856+ if(k2==VK_RETURN || k2==VK_SEPARATOR) k1='\n'; //Enter押下は単純に改行文字を入力とする
1857+ if(k1) normal_code_process(k1); //通常文字が入力された場合
1858+ else control_code_process(k2,sh); //制御文字が入力された場合
1859+ if(cursorbp1!=NULL && cx==cx1 && cy==cy1) cursorbp1=NULL;//選択範囲の開始と終了が重なったら範囲選択モード解除
1860+ }
1861+}
--- mips/tags/zoea1.00/main.h (nonexistent)
+++ mips/tags/zoea1.00/main.h (revision 148)
@@ -0,0 +1,21 @@
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+#define SYSVER1 "Zoea"
9+#define SYSVER2 "1.0"
10+#define BASVER "KM-1200"
11+
12+#define INIFILE "MACHIKAZ.INI" // 初期設定ファイル
13+#define HEXFILE "MACHIKAZ.HEX" // 実行中HEXファイル名がこれと一致した場合はエディタ起動
14+
15+#define FILENAME_FLASH_ADDRESS 0x9D005800
16+#define PIC32MX_RAMSIZE 0x10000
17+#define PIC32MX_FLASHSIZE 0x40000
18+
19+void printhex8(unsigned char d);
20+void printhex16(unsigned short d);
21+void printhex32(unsigned int d);
--- mips/tags/zoea1.00/editor.h (nonexistent)
+++ mips/tags/zoea1.00/editor.h (revision 148)
@@ -0,0 +1,29 @@
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+#define TBUFMAXLINE 201 //テキストバッファ数
8+
9+#define TBUFSIZE 200 //テキストバッファ1つのサイズ
10+#define TBUFMAXSIZE (TBUFSIZE*(TBUFMAXLINE-1)) //最大バッファ容量(バッファ1行分空ける)
11+#define EDITWIDTHX 30 //エディタ画面横幅
12+#define EDITWIDTHY 26 //エディタ画面縦幅
13+#define COLOR_NORMALTEXT 7 //通常テキスト色
14+#define COLOR_ERRORTEXT 4 //エラーメッセージテキスト色
15+#define COLOR_AREASELECTTEXT 4 //範囲選択テキスト色
16+#define COLOR_BOTTOMLINE 5 //画面最下行の色
17+#define FILEBUFSIZE 256 //ファイルアクセス用バッファサイズ
18+#define MAXFILENUM 200 //利用可能ファイル最大数
19+
20+#define ERR_FILETOOBIG -1
21+#define ERR_CANTFILEOPEN -2
22+#define ERR_CANTWRITEFILE -3
23+
24+#define TEMPFILENAME "~TEMP.BAS"
25+
26+void texteditor(void); //テキストエディタ本体
27+int runbasic(char *s,int test); //コンパイルして実行
28+extern unsigned char tempfile[13];
29+void wait60thsec(unsigned short n);
--- mips/tags/zoea1.00/debug.c (nonexistent)
+++ mips/tags/zoea1.00/debug.c (revision 148)
@@ -0,0 +1,160 @@
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+
14+
15+// Pseudo reading config setting for debug mode
16+unsigned int g_DEVCFG1=0xFF7F4DDB;
17+
18+// Construct jump assembly in boot area.
19+const unsigned int _debug_boot[] __attribute__((address(0xBFC00000))) ={
20+ 0x0B401C00,// j 0x9d007000
21+ 0x00000000,// nop
22+};
23+
24+// Use DEBUG.HEX as file name of this program.
25+const unsigned char _debug_filename[] __attribute__((address(FILENAME_FLASH_ADDRESS))) ="DEBUG.HEX";
26+
27+static const char initext[];
28+static const char bastext[];
29+
30+static char* readtext;
31+static int filepos;
32+
33+/*
34+ Override libsdfsio functions.
35+ Here, don't use SD card, but the vertual files
36+ (initext[] and bastext[]) are used.
37+*/
38+
39+FSFILE fsfile;
40+
41+size_t FSfread(void *ptr, size_t size, size_t n, FSFILE *stream){
42+ char b;
43+ size_t ret=0;
44+ if (!readtext) return 0;
45+ while(b=readtext[filepos]){
46+ filepos++;
47+ ((char*)ptr)[ret]=b;
48+ ret++;
49+ if (n<=ret) break;
50+ }
51+ return ret;
52+}
53+FSFILE* FSfopen(const char * fileName, const char *mode){
54+ int i;
55+ for(i=0;i<13;i++){
56+ if (fileName[i]=='.') break;
57+ }
58+ if (i==13) {
59+ // Unknown file name
60+ // Force BAS file
61+ readtext=(char*)&bastext[0];
62+ } else if (fileName[i+1]=='I' && fileName[i+2]=='N' && fileName[i+3]=='I') {
63+ // INI file
64+ readtext=(char*)&initext[0];
65+ } else if (fileName[i+1]=='B' && fileName[i+2]=='A' && fileName[i+3]=='S') {
66+ // BAS file
67+ readtext=(char*)&bastext[0];
68+ } else {
69+ readtext=0;
70+ return 0;
71+ }
72+ filepos=0;
73+ return &fsfile;
74+}
75+int FSfeof( FSFILE * stream ){
76+ return readtext[filepos]?1:0;
77+}
78+int FSfclose(FSFILE *fo){
79+ return 0;
80+}
81+int FSInit(void){
82+ return 1;
83+}
84+int FSremove (const char * fileName){
85+ return 0;
86+}
87+size_t FSfwrite(const void *ptr, size_t size, size_t n, FSFILE *stream){
88+ return 0;
89+}
90+
91+int FindFirst (const char * fileName, unsigned int attr, SearchRec * rec){
92+ return 0;
93+}
94+int FindNext (SearchRec * rec){
95+ return 0;
96+}
97+
98+/*
99+ ps2init() is not called.
100+ Instead, not_ps2init_but_init_Timer1() is called.
101+ Timer1 is used to update drawcount and drawing gloval variables.
102+*/
103+
104+int not_ps2init_but_init_Timer1(){
105+ PR1=0x0FFF;
106+ TMR1=0;
107+ IFS0bits.T1IF=0;
108+ T1CON=0x8000;
109+ // Timer1 interrupt: priority 4
110+ IPC1bits.T1IP=4;
111+ IPC1bits.T1IS=0;
112+ IEC0bits.T1IE=1;
113+
114+ return 0;
115+}
116+
117+#pragma interrupt timer1Int IPL4SOFT vector 4
118+
119+void timer1Int(){
120+ IFS0bits.T1IF=0;
121+ if (drawing) {
122+ drawing=0;
123+ drawcount++;
124+ } else {
125+ drawing=1;
126+ }
127+}
128+
129+/*
130+ initext[] and bastext[] are vertual files
131+ as "MACHIKAN.INI" and "DEBUG.BAS".
132+*/
133+
134+
135+static const char initext[]=
136+"#PRINT\n"
137+"#PRINT\n";
138+
139+
140+static const char bastext[]=
141+"CLS\n"
142+"\n";
143+
144+/*
145+ Test function for constructing assemblies from C codes.
146+*/
147+
148+int _debug_test(int a0, int a1){
149+// if (a0<0xa0008192) return 0xa0000000;
150+ asm volatile("lw $v1,0($v1)");
151+}
152+
153+/*
154+ Break point used for debugging object code.
155+
156+g_object[g_objpos++]=0x0000000d;// break 0x0
157+
158+*/
159+
160+#endif // __DEBUG
--- mips/tags/zoea1.00/library.c (nonexistent)
+++ mips/tags/zoea1.00/library.c (revision 148)
@@ -0,0 +1,984 @@
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+ i--;
68+ continue;
69+ }
70+ // DATA region found.
71+ in_data=(code&0x0000FFFF)-1;
72+ pos=i+2;
73+ skip=code2&0x03;
74+ break;
75+ }
76+ if (g_objpos<=i) {
77+ err_data_not_found();
78+ return 0;
79+ }
80+ }
81+ if (label) {
82+ // RESTORE function. Return pointer.
83+ return ((int)&g_object[pos])+skip;
84+ } else {
85+ switch(mode){
86+ case 0:
87+ // READ() function
88+ in_data--;
89+ return g_object[pos++];
90+ case 1:
91+ default:
92+ // CREAD() function
93+ i=g_object[pos];
94+ i>>=skip*8;
95+ i&=0xff;
96+ if ((++skip)==4) {
97+ skip=0;
98+ in_data--;
99+ pos++;
100+ }
101+ return i;
102+ }
103+ }
104+}
105+
106+void reset_dataread(){
107+ lib_read(2,1);
108+}
109+
110+char* lib_midstr(int var_num, int pos, int len){
111+ int i;
112+ char* str;
113+ char* ret;
114+ if (0<=pos) {
115+ // String after "pos" position.
116+ str=(char*)(g_var_mem[var_num]+pos);
117+ } else {
118+ // String right "pos" characters.
119+ // Determine length
120+ str=(char*)g_var_mem[var_num];
121+ for(i=0;str[i];i++);
122+ if (0<=(i+pos)) {
123+ str=(char*)(g_var_mem[var_num]+i+pos);
124+ }
125+ }
126+ if (len<0) {
127+ // Length is not specified.
128+ // Return the string to the end.
129+ return str;
130+ }
131+ // Length is specified.
132+ // Construct temporary string containing specified number of characters.
133+ ret=alloc_memory((len+1+3)/4,-1);
134+ // Copy string.
135+ for(i=0;(ret[i]=str[i])&&(i<len);i++);
136+ ret[len]=0x00;
137+ return ret;
138+}
139+
140+void lib_clear(void){
141+ int i;
142+ // All variables will be integer 0
143+ for(i=0;i<26;i++){
144+ g_var_mem[i]=0;
145+ }
146+ // Clear memory allocation area
147+ for(i=0;i<ALLOC_BLOCK_NUM;i++){
148+ g_var_size[i]=0;
149+ }
150+ // Cancel PCG
151+ stopPCG();
152+ g_pcg_font=0;
153+}
154+
155+void lib_let_str(char* str, int var_num){
156+ int begin,end,size;
157+ // Save pointer
158+ g_var_mem[var_num]=(int)str;
159+ // Determine size
160+ for(size=0;str[size];size++);
161+ // Check if str is in heap area.
162+ begin=(int)str;
163+ end=(int)(&str[size]);
164+ if (begin<(int)(&g_heap_mem[0]) || (int)(&g_heap_mem[g_max_mem])<=end) {
165+ // String is not within allcated block
166+ return;
167+ }
168+ // Str is in heap area. Calculate values stored in heap data dimension
169+ begin-=(int)(&g_heap_mem[0]);
170+ begin>>=2;
171+ end-=(int)(&g_heap_mem[0]);
172+ end>>=2;
173+ size=end-begin+1;
174+ g_var_pointer[var_num]=begin;
175+ g_var_size[var_num]=size;
176+}
177+
178+int lib_rnd(){
179+ int y;
180+ y=g_rnd_seed;
181+ y = y ^ (y << 13);
182+ y = y ^ (y >> 17);
183+ y = y ^ (y << 5);
184+ g_rnd_seed=y;
185+ return y&0x7fff;
186+}
187+
188+char* lib_chr(int num){
189+ char* str;
190+ str=alloc_memory(1,-1);
191+ str[0]=num&0x000000FF;
192+ str[1]=0x00;
193+ return str;
194+}
195+
196+char* lib_dec(int num){
197+ char* str;
198+ int i,j,minus;
199+ char b[12];
200+ b[11]=0x00;
201+ if (num<0) {
202+ minus=1;
203+ num=0-num;
204+ } else {
205+ minus=0;
206+ }
207+ for (i=10;0<i;i--) {
208+ if (num==0 && i<10) break;
209+ b[i]='0'+rem10_32(num);
210+ num=div10_32(num);
211+ }
212+ if (minus) {
213+ b[i]='-';
214+ } else {
215+ i++;
216+ }
217+ str=alloc_memory(3,-1);
218+ for(j=0;str[j]=b[i++];j++);
219+ return str;
220+}
221+
222+char* lib_hex(int num, int width){
223+ char* str;
224+ int i,j,minus;
225+ char b[8];
226+ str=alloc_memory(3,-1);
227+ for(i=0;i<8;i++){
228+ b[i]="0123456789ABCDEF"[(num>>(i<<2))&0x0F];
229+ }
230+ // Width must be between 0 and 8;
231+ if (width<0||8<width) width=8;
232+ if (width==0) {
233+ // Width not asigned. Use minimum width.
234+ for(i=7;0<i;i--){
235+ if ('0'<b[i]) break;
236+ }
237+ } else {
238+ // Constant width
239+ i=width-1;
240+ }
241+ // Copy string to allocated block.
242+ for(j=0;0<=i;i--){
243+ str[j++]=b[i];
244+ }
245+ str[j]=0x00;
246+ return str;
247+}
248+
249+char* lib_connect_string(char* str1, char* str2){
250+ int i,j;
251+ char b;
252+ char* result;
253+ // Determine total length
254+ for(i=0;str1[i];i++);
255+ for(j=0;str2[j];j++);
256+ // Allocate a block for new string
257+ result=alloc_memory((i+j+1+3)/4,-1);
258+ // Create connected strings
259+ for(i=0;b=str1[i];i++) result[i]=b;
260+ for(j=0;b=str2[j];j++) result[i+j]=b;
261+ result[i+j]=0x00;
262+ free_temp_str(str1);
263+ free_temp_str(str2);
264+ return result;
265+}
266+
267+void lib_string(int mode){
268+ int i;
269+ switch(mode){
270+ case 0:
271+ // CR
272+ printchar('\n');
273+ return;
274+ case 1:
275+ // ,
276+ i=rem10_32((unsigned int)(cursor-TVRAM));
277+ printstr(" "+i);
278+ return;
279+ default:
280+ return;
281+ }
282+}
283+
284+void* lib_label(unsigned int label){
285+ // This routine is used to jump to address dynamically determined
286+ // in the code; for example: "GOTO 100+I"
287+ unsigned int i,code,search;
288+ void* ret;
289+ if (label&0xFFFF0000) {
290+ // Label is not supported.
291+ // Line number must bs less than 65536.
292+ err_label_not_found();
293+ } else {
294+ // Line number
295+ ret=search_label(label);
296+ if (ret) return ret;
297+ // Line number not found.
298+ err_label_not_found();
299+ }
300+}
301+
302+int lib_keys(int mask){
303+ int keys;
304+ // Enable tact switches
305+ if (inPS2MODE()) {
306+ buttonmode();
307+ }
308+
309+ keys=KEYPORT;
310+ keys=
311+ ((keys&KEYUP)? 0:1)|
312+ ((keys&KEYDOWN)? 0:2)|
313+ ((keys&KEYLEFT)? 0:4)|
314+ ((keys&KEYRIGHT)? 0:8)|
315+ ((keys&KEYSTART)? 0:16)|
316+ ((keys&KEYFIRE)? 0:32);
317+ return mask&keys;
318+}
319+
320+int lib_val(char* str){
321+ int i;
322+ int val=0;
323+ int sign=1;
324+ char b;
325+ // Skip blanc
326+ for(i=0;0<=str[i] && str[i]<0x21;i++);
327+ // Skip '+'
328+ if (str[i]=='+') i++;
329+ // Check '-'
330+ if (str[i]=='-') {
331+ sign=-1;
332+ i++;
333+ }
334+ // Check '0x' or '$'
335+ if (str[i]=='$' || str[i]=='0' && (str[i+1]=='x' || str[i+1]=='X')) {
336+ // Hexadecimal
337+ if (str[i++]=='0') i++;
338+ while(1) {
339+ b=str[i++];
340+ if ('0'<=b && b<='9') {
341+ val<<=4;
342+ val+=b-'0';
343+ } else if ('a'<=b && b<='f') {
344+ val<<=4;
345+ val+=b-'a'+10;
346+ } else if ('A'<=b && b<='F') {
347+ val<<=4;
348+ val+=b-'A'+10;
349+ } else {
350+ break;
351+ }
352+ }
353+ } else {
354+ // Decimal
355+ while(1) {
356+ b=str[i++];
357+ if ('0'<=b && b<='9') {
358+ val*=10;
359+ val+=b-'0';
360+ } else {
361+ break;
362+ }
363+ }
364+ }
365+ return val*sign;
366+}
367+
368+char* lib_input(){
369+ // Allocate memory for strings with 63 characters
370+ char *str=calloc_memory((63+1)/4,-1);
371+ // Enable PS/2 keyboard
372+ if (!inPS2MODE()) {
373+ ps2mode();
374+ ps2init();
375+ }
376+ // Clear key buffer
377+ do ps2readkey();
378+ while(vkey!=0);
379+ // Get string as a line
380+ lineinput(str,63);
381+ check_break();
382+ return str;
383+}
384+
385+unsigned char lib_inkey(int key){
386+ int i;
387+ // Enable PS/2 keyboard
388+ if (!inPS2MODE()) {
389+ ps2mode();
390+ ps2init();
391+ }
392+ if (key) {
393+ return ps2keystatus[key&0xff];
394+ } else {
395+ for(i=0;i<256;i++){
396+ if (ps2keystatus[i]) return i;
397+ }
398+ return 0;
399+ }
400+}
401+
402+void lib_usepcg(int mode){
403+ // Modes; 0: stop PCG, 1: use PCG, 2: reset PCG and use it
404+ switch(mode){
405+ case 0:
406+ // Stop PCG
407+ stopPCG();
408+ break;
409+ case 2:
410+ // Reset PCG and use it
411+ if (g_pcg_font) {
412+ free_temp_str(g_pcg_font);
413+ g_pcg_font=0;
414+ }
415+ // Continue to case 1:
416+ case 1:
417+ default:
418+ // Use PCG
419+ if (g_pcg_font) {
420+ startPCG(g_pcg_font,0);
421+ } else {
422+ g_pcg_font=alloc_memory(256*8/4,ALLOC_PCG_BLOCK);
423+ startPCG(g_pcg_font,1);
424+ }
425+ break;
426+ }
427+}
428+
429+void lib_pcg(unsigned int ascii,unsigned int fontdata1,unsigned int fontdata2){
430+ unsigned int* pcg;
431+ // If USEPCG has not yet executed, do now.
432+ if (!g_pcg_font) lib_usepcg(1);
433+ pcg=(unsigned int*)g_pcg_font;
434+ // 0 <= ascii <= 0xff
435+ ascii&=0xff;
436+ // Update font data
437+ ascii<<=1;
438+ pcg[ascii]=(fontdata1>>24)|((fontdata1&0xff0000)>>8)|((fontdata1&0xff00)<<8)|(fontdata1<<24);
439+ pcg[ascii+1]=(fontdata2>>24)|((fontdata2&0xff0000)>>8)|((fontdata2&0xff00)<<8)|(fontdata2<<24);
440+}
441+
442+void lib_scroll(int x,int y){
443+ int i,j;
444+ int vector=y*WIDTH_X+x;
445+ if (vector<0) {
446+ // Copy data from upper address to lower address
447+ for(i=0-vector;i<WIDTH_X*WIDTH_Y;i++){
448+ TVRAM[i+vector]=TVRAM[i];
449+ TVRAM[WIDTH_X*WIDTH_Y+i+vector]=TVRAM[WIDTH_X*WIDTH_Y+i];
450+ }
451+ } else if (0<vector) {
452+ // Copy data from lower address to upper address
453+ for(i=WIDTH_X*WIDTH_Y-vector-1;0<=i;i--){
454+ TVRAM[i+vector]=TVRAM[i];
455+ TVRAM[WIDTH_X*WIDTH_Y+i+vector]=TVRAM[WIDTH_X*WIDTH_Y+i];
456+ }
457+ } else {
458+ return;
459+ }
460+ if (x<0) {
461+ // Fill blanc at right
462+ for(i=x;i<0;i++){
463+ for(j=WIDTH_X+i;j<WIDTH_X*WIDTH_Y;j+=WIDTH_X){
464+ TVRAM[j]=0x00;
465+ TVRAM[WIDTH_X*WIDTH_Y+j]=cursorcolor;
466+ }
467+ }
468+ } else if (0<x) {
469+ // Fill blanc at left
470+ for(i=0;i<x;i++){
471+ for(j=i;j<WIDTH_X*WIDTH_Y;j+=WIDTH_X){
472+ TVRAM[j]=0x00;
473+ TVRAM[WIDTH_X*WIDTH_Y+j]=cursorcolor;
474+ }
475+ }
476+ }
477+ if (y<0) {
478+ // Fill blanc at bottom
479+ for(i=WIDTH_X*(WIDTH_Y+y);i<WIDTH_X*WIDTH_Y;i++){
480+ TVRAM[i]=0x00;
481+ TVRAM[WIDTH_X*WIDTH_Y+i]=cursorcolor;
482+ }
483+ } else if (0<y) {
484+ // Fill blanc at top
485+ for(i=0;i<WIDTH_X*y;i++){
486+ TVRAM[i]=0x00;
487+ TVRAM[WIDTH_X*WIDTH_Y+i]=cursorcolor;
488+ }
489+ }
490+}
491+
492+void lib_wait(int period){
493+ int i;
494+ unsigned short dcount;
495+ for(i=0;i<period;i++){
496+ dcount=drawcount;
497+ while(dcount==drawcount){
498+ asm (WAIT);
499+ check_break();
500+ }
501+ }
502+}
503+
504+void allocate_graphic_area(){
505+ if (!g_graphic_area) {
506+ // Use this pointer like unsigned short GVRAM[G_H_WORD*G_Y_RES] __attribute__ ((aligned (4)));
507+ g_graphic_area=(unsigned short*)alloc_memory(G_H_WORD*G_Y_RES/2,ALLOC_GRAPHIC_BLOCK);
508+ // Start graphic and clear screen
509+ init_graphic(g_graphic_area);
510+ // Move current point to (0,0)
511+ g_prev_x=g_prev_y=0;
512+ }
513+}
514+
515+void lib_usegraphic(int mode){
516+ // Modes; 0: stop GRAPHIC, 1: use GRAPHIC, 2: reset GRAPHIC and use it
517+ switch(mode){
518+ case 0:
519+ if (g_use_graphic){
520+ // Stop GRAPHIC if used
521+ set_graphmode(0);
522+ g_use_graphic=0;
523+ // Set timer4 for tempo
524+ PR4=59473; // 3632*262/16-1
525+ } else {
526+ // Prepare GRAPHIC area if not used and not allcated.
527+ allocate_graphic_area();
528+ }
529+ break;
530+ case 2:
531+ // Reset GRAPHIC and use it
532+ g_graphic_area=0;
533+ // Continue to case 1:
534+ case 1:
535+ case 3:
536+ default:
537+ // Use GRAPHIC
538+ allocate_graphic_area();
539+ // Start showing GRAPHIC with mode 1, but not with mode 3
540+ if (mode !=3 && !g_use_graphic){
541+ set_graphmode(1);
542+ g_use_graphic=1;
543+ // Set timer4 for tempo
544+ PR4=55756; // ~=3405*262/16-1(55755.875)
545+ }
546+ break;
547+ }
548+}
549+
550+int lib_graphic(int a0, int a1, int v0){
551+ unsigned char b;
552+ enum functions func=(enum functions)(a0>>24);
553+ int x1=(a0>>12)&0x0FFF;
554+ int y1=a0&0x0FFF;
555+ int x2=(a1>>12)&0x0FFF;
556+ int y2=a1&0x0FFF;
557+ // Disable if graphic area is not defined.
558+ if (!g_graphic_area) return;
559+ // Support 12 bit signed integer.
560+ if (x1&0x0800) x1|=0x0FFFFF000;
561+ if (y1&0x0800) y1|=0x0FFFFF000;
562+ if (x2&0x0800) x2|=0x0FFFFF000;
563+ if (y2&0x0800) y2|=0x0FFFFF000;
564+ // If C is omitted in parameters, use current color.
565+ if (v0==-1) {
566+ v0=g_gcolor;
567+ }
568+ // If X1 or Y1 is -2048 (0xFFFFF800/0x0800), use the previous values.
569+ if (x1==-2048) x1=g_prev_x;
570+ if (y1==-2048) y1=g_prev_y;
571+ switch(func){
572+ case FUNC_POINT:// X1,Y1
573+ g_prev_x=x1;
574+ g_prev_y=y1;
575+ break;
576+ case FUNC_PSET:// X1,Y1[,C]
577+ g_pset(x1,y1,v0&0x0F);
578+ g_prev_x=x1;
579+ g_prev_y=y1;
580+ break;
581+ case FUNC_LINE:// X1,Y1,X2,Y2[,C]
582+ if (y1==y2) g_hline(x1,x2,y1,v0&0x0F);
583+ else g_gline(x1,y1,x2,y2,v0&0x0F);
584+ g_prev_x=x2;
585+ g_prev_y=y2;
586+ break;
587+ case FUNC_BOXFILL:// X1,Y1,X2,Y2[,C]
588+ g_boxfill(x1,y1,x2,y2,v0&0x0F);
589+ g_prev_x=x2;
590+ g_prev_y=y2;
591+ break;
592+ case FUNC_CIRCLE:// X1,Y1,R[,C]
593+ g_circle(x1,y1,x2,v0&0x0F);
594+ g_prev_x=x1;
595+ g_prev_y=y1;
596+ break;
597+ case FUNC_CIRCLEFILL:// X1,Y1,R[,C]
598+ g_circlefill(x1,y1,x2,v0&0x0F);
599+ g_prev_x=x1;
600+ g_prev_y=y1;
601+ break;
602+ case FUNC_GPRINT:// X1,Y1,C,BC,S$
603+ g_printstr(x1,y1,x2,y2,(unsigned char*)v0);
604+ // Move current X,Y according to the string
605+ while(b=((unsigned char*)v0)[0]){
606+ v0++;
607+ if (b==0x0d) {
608+ x1=0;
609+ y1+=8;
610+ } else {
611+ x1+=8;
612+ }
613+ }
614+ g_prev_x=x1;
615+ g_prev_y=y1;
616+ break;
617+ case FUNC_PUTBMP2:// X1,Y1,M,N,BMP(label)
618+ // Search CDATA
619+ // It starts from either 0x00000020,0x00000021,0x00000022, or 0x00000023.
620+ while((((unsigned int*)v0)[0]&0xfffffffc)!=0x00000020) v0+=4;
621+ // CDATA starts from next word.
622+ // MLB 3 bytes show skip byte(s).
623+ v0+=4+(((unsigned int*)v0)[0]&0x03);
624+ // Contunue to FUNC_PUTBMP.
625+ case FUNC_PUTBMP:// X1,Y1,M,N,BMP(pointer)
626+ g_putbmpmn(x1,y1,x2,y2,(const unsigned char*)v0);
627+ g_prev_x=x1;
628+ g_prev_y=y1;
629+ break;
630+ case FUNC_GCOLOR:// (X1,Y1)
631+ v0=g_color(x1,y1);
632+ break;
633+ default:
634+ break;
635+ }
636+ return v0;
637+}
638+
639+void lib_var_push(int* sp,unsigned int flags){
640+ unsigned int strflags=0;
641+ int varnum;
642+ int stack=0;
643+ // Store flags in stack
644+ // Note that sp[1] is used for string return address
645+ sp[2]=flags;
646+ for(varnum=0;varnum<26;varnum++){
647+ if (flags&1) {
648+ sp[(stack++)+4]=g_var_mem[varnum];
649+ if (g_var_size[varnum] && g_var_mem[varnum]==(int)(&g_var_pointer[varnum])) {
650+ // strflags change using varnum
651+ strflags|=1<<varnum;
652+ // Copy to VAR_BLOCK
653+ move_to_perm_block(varnum);
654+ }
655+ // Clear variable
656+ g_var_mem[varnum]=0;
657+ }
658+ flags>>=1;
659+ }
660+ sp[3]=strflags;
661+}
662+void lib_var_pop(int* sp){
663+ // Note that sp is 4 bytes larger than that in lib_var_push
664+ unsigned int flags;
665+ unsigned int strflags;
666+ int varnum;
667+ int stack=0;
668+ flags=sp[1];
669+ strflags=sp[2];
670+ for(varnum=0;varnum<26;varnum++){
671+ if (flags&1) {
672+ g_var_mem[varnum]=sp[(stack++)+3];
673+ if (strflags&1) {
674+ // Restore from VAR_BLOCK
675+ move_from_perm_block(varnum);
676+ }
677+ }
678+ flags>>=1;
679+ strflags>>=1;
680+ }
681+}
682+
683+int lib_system(int a0,int v0){
684+ switch(a0){
685+ // Version info
686+ case 0: return (int)SYSVER1;
687+ case 1: return (int)SYSVER2;
688+ case 2: return (int)BASVER;
689+ case 3: return (int)FILENAME_FLASH_ADDRESS;
690+ // Display info
691+ case 20: return WIDTH_X;
692+ case 21: return WIDTH_Y;
693+ case 22: return G_X_RES;
694+ case 23: return G_Y_RES;
695+ case 24: return cursorcolor;
696+ case 25: return g_gcolor;
697+ case 26: return ((int)(cursor-TVRAM))%WIDTH_X;
698+ case 27: return ((int)(cursor-TVRAM))/WIDTH_X;
699+ case 28: return g_prev_x;
700+ case 29: return g_prev_y;
701+ // Keyboard info
702+ case 40: return (int)inPS2MODE();
703+ case 41: return (int)vkey;
704+ case 42: return (int)lockkey;
705+ case 43: return (int)keytype;
706+ // Pointers to gloval variables
707+ case 100: return (int)&g_var_mem[0];
708+ case 101: return (int)&g_rnd_seed;
709+ case 102: return (int)&TVRAM[0];
710+ case 103: return (int)&FontData[0];
711+ case 104: return (int)g_var_mem[ALLOC_PCG_BLOCK];
712+ case 105: return (int)g_var_mem[ALLOC_GRAPHIC_BLOCK];
713+ // Change system settings
714+ case 200:
715+ // ON/OFF monitor
716+ if (v0) {
717+ start_composite();
718+ } else {
719+ stop_composite();
720+ }
721+ break;
722+ default:
723+ break;
724+ }
725+ return 0;
726+}
727+
728+char* lib_sprintf(char* format, int data){
729+ char* str;
730+ int i;
731+ char temp[4];
732+ if (!format) format="%g";
733+ i=snprintf((char*)(&temp[0]),4,format,data)+1;
734+ str=alloc_memory((i+3)/4,-1);
735+ snprintf(str,i,format,data);
736+ return str;
737+}
738+
739+int lib_floatfuncs(int ia0,int iv0,enum functions a1){
740+ volatile float a0,v0;
741+ ((int*)(&a0))[0]=ia0;
742+ ((int*)(&v0))[0]=iv0;
743+ switch(a1){
744+ case FUNC_FLOAT:
745+ v0=(float)iv0;
746+ break;
747+ case FUNC_INT:
748+ return (int)v0;
749+ case FUNC_VALSHARP:
750+ v0=strtof((const char*)iv0,0);
751+ break;
752+ case FUNC_SIN:
753+ v0=sinf(v0);
754+ break;
755+ case FUNC_COS:
756+ v0=cosf(v0);
757+ break;
758+ case FUNC_TAN:
759+ v0=tanf(v0);
760+ break;
761+ case FUNC_ASIN:
762+ v0=asinf(v0);
763+ break;
764+ case FUNC_ACOS:
765+ v0=acosf(v0);
766+ break;
767+ case FUNC_ATAN:
768+ v0=atanf(v0);
769+ break;
770+ case FUNC_SINH:
771+ v0=sinhf(v0);
772+ break;
773+ case FUNC_COSH:
774+ v0=coshf(v0);
775+ break;
776+ case FUNC_TANH:
777+ v0=tanhf(v0);
778+ break;
779+ case FUNC_EXP:
780+ v0=expf(v0);
781+ break;
782+ case FUNC_LOG:
783+ v0=logf(v0);
784+ break;
785+ case FUNC_LOG10:
786+ v0=log10f(v0);
787+ break;
788+ case FUNC_POW:
789+ v0=powf(v0,a0);
790+ break;
791+ case FUNC_SQRT:
792+ v0=sqrtf(v0);
793+ break;
794+ case FUNC_CEIL:
795+ v0=ceilf(v0);
796+ break;
797+ case FUNC_FLOOR:
798+ v0=floorf(v0);
799+ break;
800+ case FUNC_FABS:
801+ v0=fabsf(v0);
802+ break;
803+ case FUNC_MODF:
804+ v0=modff(v0,(void*)&a0);
805+ break;
806+ case FUNC_FMOD:
807+ v0=fmodf(v0,a0);
808+ break;
809+ default:
810+ err_unknown();
811+ break;
812+ }
813+ return ((int*)(&v0))[0];
814+};
815+
816+int* lib_dim(int varnum, int argsnum, int* sp){
817+ int i,j;
818+ static int* heap;
819+ // Calculate total length.
820+ int len=0; // Total length
821+ int size=1; // Size of current block
822+ for(i=1;i<=argsnum;i++){
823+ size*=sp[i]+1;
824+ len+=size;
825+ }
826+ // Allocate memory
827+ heap=calloc_memory(len,varnum);
828+ // Construct pointers
829+ len=0;
830+ size=1;
831+ for(i=1;i<argsnum;i++){
832+ size*=sp[i]+1;
833+ for(j=0;j<size;j++){
834+ heap[len+j]=(int)&heap[len+size+(sp[i+1]+1)*j];
835+ }
836+ len+=size;
837+ }
838+ return heap;
839+};
840+
841+int _call_library(int a0,int a1,int a2,enum libs a3);
842+
843+void call_library(void){
844+ // Store s6 in g_s6
845+ asm volatile("la $a2,%0"::"i"(&g_s6));
846+ asm volatile("sw $s6,0($a2)");
847+ // Copy $v0 to $a2 as 3rd argument of function
848+ asm volatile("addu $a2,$v0,$zero");
849+ asm volatile("j _call_library");
850+}
851+
852+int _call_library(int a0,int a1,int v0,enum libs a3){
853+ // usage: call_lib_code(LIB_XXXX);
854+ // Above code takes 2 words.
855+ check_break();
856+ switch(a3){
857+ case LIB_FLOAT:
858+ return lib_float(a0,v0,(enum operator)a1); // see operator.c
859+ case LIB_FLOATFUNCS:
860+ return lib_floatfuncs(a0,v0,(enum functions)a1);
861+ case LIB_STRNCMP:
862+ return strncmp((char*)a0,(char*)a1,v0);
863+ case LIB_MIDSTR:
864+ return (int)lib_midstr(a1,v0,a0);
865+ case LIB_RND:
866+ return (int)lib_rnd();
867+ case LIB_DEC:
868+ return (int)lib_dec(v0);
869+ case LIB_HEX:
870+ return (int)lib_hex(v0,a0);
871+ case LIB_CHR:
872+ return (int)lib_chr(v0);
873+ case LIB_VAL:
874+ return lib_val((char*)v0);
875+ case LIB_LETSTR:
876+ lib_let_str((char*)v0,a0);
877+ return;
878+ case LIB_CONNECT_STRING:
879+ return (int)lib_connect_string((char*)a0, (char*)v0);
880+ case LIB_STRING:
881+ lib_string(a0);
882+ return v0;
883+ case LIB_PRINTSTR:
884+ printstr((char*)v0);
885+ return v0;
886+ case LIB_GRAPHIC:
887+ return lib_graphic(a0,a1,v0);
888+ case LIB_SPRINTF:
889+ return (int)lib_sprintf((char*)v0,a0);
890+ case LIB_VAR_PUSH:
891+ lib_var_push((int*)a1,a0);
892+ return v0;
893+ case LIB_VAR_POP:
894+ lib_var_pop((int*)a1);
895+ return v0;
896+ case LIB_SCROLL:
897+ lib_scroll(a0,v0);
898+ return v0;
899+ case LIB_KEYS:
900+ return lib_keys(v0);
901+ case LIB_INKEY:
902+ return (int)lib_inkey(v0);
903+ case LIB_CURSOR:
904+ setcursor(a0,v0,cursorcolor);
905+ return v0;
906+ case LIB_SOUND:
907+ set_sound((unsigned long*)v0);
908+ return v0;
909+ case LIB_MUSICFUNC:
910+ return musicRemaining();
911+ case LIB_MUSIC:
912+ set_music((char*)v0);
913+ return v0;
914+ case LIB_SETDRAWCOUNT:
915+ drawcount=(v0&0x0000FFFF);
916+ return v0;
917+ case LIB_DRAWCOUNT:
918+ return drawcount;
919+ case LIB_SYSTEM:
920+ return lib_system(a0,v0);
921+ case LIB_RESTORE:
922+ return lib_read(0,v0);
923+ case LIB_RESTORE2:
924+ return lib_read(1,v0);
925+ case LIB_READ:
926+ return lib_read(0,0);
927+ case LIB_CREAD:
928+ return lib_read(1,0);
929+ case LIB_LABEL:
930+ return (int)lib_label(v0);
931+ case LIB_INPUT:
932+ return (int)lib_input();
933+ case LIB_USEGRAPHIC:
934+ lib_usegraphic(v0);
935+ return v0;
936+ case LIB_USEPCG:
937+ lib_usepcg(v0);
938+ return v0;
939+ case LIB_PCG:
940+ lib_pcg(a0,a1,v0);
941+ return v0;
942+ case LIB_BGCOLOR: // BGCOLOR R,G,B
943+ set_bgcolor(v0,a0,a1); //set_bgcolor(b,r,g);
944+ return v0;
945+ case LIB_PALETTE: // PALETTE N,R,G,B
946+ set_palette(a0,v0,(a1>>16)&255,a1&255); // set_palette(n,b,r,g);
947+ return v0;
948+ case LIB_GPALETTE:// GPALETTE N,R,G,B
949+ if (g_graphic_area) g_set_palette(a0,v0,(a1>>16)&255,a1&255); // g_set_palette(n,b,r,g);
950+ return v0;
951+ case LIB_CLS:
952+ clearscreen();
953+ return v0;
954+ case LIB_GCLS:
955+ if (g_graphic_area) g_clearscreen();
956+ g_prev_x=g_prev_y=0;
957+ return v0;
958+ case LIB_COLOR:
959+ setcursorcolor(v0);
960+ return v0;
961+ case LIB_GCOLOR:
962+ g_gcolor=v0;
963+ return v0;
964+ case LIB_WAIT:
965+ lib_wait(v0);
966+ return v0;
967+ case LIB_CLEAR:
968+ lib_clear();
969+ return v0;
970+ case LIB_DIM:
971+ return (int)lib_dim(a0,a1,(int*)v0);
972+#ifdef __DEBUG
973+ case LIB_DEBUG:
974+ asm volatile("nop");
975+ return v0;
976+#endif
977+ case LIB_DIV0:
978+ err_div_zero();
979+ return v0;
980+ default:
981+ err_unknown();
982+ return v0;
983+ }
984+}
\ No newline at end of file
--- mips/tags/zoea1.00/music.c (nonexistent)
+++ mips/tags/zoea1.00/music.c (revision 148)
@@ -0,0 +1,483 @@
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+ Timer4: 1/32 prescaler: 1789772.5 Hz
16+ Timer4 29737 counts: 262 NTSC lines.
17+*/
18+
19+/*
20+ c: 1722
21+ B: 1825
22+ A#: 1933
23+ A: 2048
24+ G#: 2170
25+ G: 2299
26+ F#: 2435
27+ F: 2580
28+ E: 2734
29+ D#: 2896
30+ D: 3067
31+ C#: 3251
32+ C: 3444
33+ Cb: 3650
34+*/
35+
36+const static int g_keys[]={
37+ 1933,1722,3251,2896,2580,2435,2170,// 0 7# C# A#m
38+ 1933,1825,3251,2896,2580,2435,2170,// 7 6# F# D#m
39+ 1933,1825,3251,2896,2734,2435,2170,// 14 5# B G#m
40+ 2048,1825,3251,2896,2734,2435,2170,// 21 4# E C#m
41+ 2048,1825,3251,3067,2734,2435,2170,// 28 3# A F#m
42+ 2048,1825,3251,3067,2734,2435,2299,// 35 2# D Bm
43+ 2048,1825,3444,3067,2734,2435,2299,// 42 1# G Em
44+ 2048,1825,3444,3067,2734,2580,2299,// 49 0 C Am
45+ 2048,1933,3444,3067,2734,2580,2299,// 56 1b F Dm
46+ 2048,1933,3444,3067,2896,2580,2299,// 63 2b Bb Gm
47+ 2170,1933,3444,3067,2896,2580,2299,// 70 3b Eb Cm
48+ 2170,1933,3444,3251,2896,2580,2299,// 77 4b Ab Fm
49+ 2170,1933,3444,3251,2896,2580,2435,// 84 5b Db Bbm
50+ 2170,1933,3650,3251,2896,2580,2435,// 91 6b Gb Ebm
51+ 2170,1933,3650,3251,2896,2734,2435 // 98 7b Cb Abm
52+};
53+
54+/*
55+ 2^(1/12) ~= 69433/(2^16)
56+ 1/(2^(1/12) ~= 1933/(2^11)
57+*/
58+
59+#define toneFlat(x) ((((unsigned long)x)*69433)>>16)
60+#define toneSharp(x) ((((unsigned long)x)*1933)>>11)
61+
62+/* local global vars */
63+static int* g_tones;
64+static int g_qvalue;
65+static int g_lvalue;
66+static int g_mpoint;
67+static char* g_mstr;
68+static int g_mspos;
69+static unsigned short g_music[32];
70+static unsigned short g_sound[32];
71+static unsigned short g_musiclen[32];
72+static unsigned char g_soundlen[32];
73+static int g_musicstart;
74+static int g_musicend;
75+static int g_musicwait;
76+static int g_soundstart;
77+static int g_soundend;
78+static int g_soundwait;
79+static int g_soundrepeat;
80+
81+int musicRemaining(){
82+ return (g_musicend-g_musicstart)&31;
83+}
84+
85+#pragma interrupt timer4int IPL3SOFT vector 16
86+void timer4int(){
87+ unsigned int i;
88+ // This function is called every 1/60 sec.
89+ IFS0CLR=_IFS0_T4IF_MASK; //IFS0bits.T4IF=0;
90+ if (g_soundstart!=g_soundend){
91+ // Start timer & OC4
92+ i=g_sound[g_soundstart];
93+ if (i<0xffff) {
94+ T3CONSET=0x8000;
95+ PR3=i;
96+ if (i<TMR3) TMR3=0;
97+ } else {
98+ T3CONCLR=0x8000;
99+ }
100+ if ((--g_soundwait)<=0) {
101+ g_soundstart++;
102+ if (g_soundstart==g_soundend || 31<g_soundstart) {
103+ g_soundstart=0;
104+ g_soundrepeat--;
105+ if (0<g_soundrepeat) {
106+ g_soundwait=g_soundlen[g_soundstart];
107+ } else {
108+ g_soundend=g_soundrepeat=g_soundwait=0;
109+ }
110+ } else {
111+ g_soundwait=g_soundlen[g_soundstart];
112+ }
113+ }
114+ // Shift music data even though without output.
115+ if (g_musicstart!=g_musicend) {
116+ if ((--g_musicwait)<=0) {
117+ g_musicstart++;
118+ g_musicstart&=31;
119+ g_musicwait=g_musiclen[g_musicstart];
120+ }
121+ }
122+ } else if (g_musicstart!=g_musicend) {
123+ // Start timer & OC4
124+ i=g_music[g_musicstart];
125+ if (i<0xffff) {
126+ T3CONSET=0x8000;
127+ PR3=i;
128+ if (i<TMR3) TMR3=0;
129+ } else {
130+ T3CONCLR=0x8000;
131+ }
132+ if ((--g_musicwait)<=0) {
133+ g_musicstart++;
134+ g_musicstart&=31;
135+ g_musicwait=g_musiclen[g_musicstart];
136+ }
137+ } else {
138+ // Stop timer
139+ T3CONCLR=0x8000;
140+ }
141+}
142+
143+int musicGetNum(){
144+ int i, ret;
145+ char b;
146+ // Skip non number character
147+ for(i=0;(b=g_mstr[g_mspos+i])<'0' && '9'<g_mstr[g_mspos+i];i++);
148+ // Determine the number
149+ ret=0;
150+ while('0'<=b && b<='9'){
151+ ret*=10;
152+ ret+=b-'0';
153+ i++;
154+ b=g_mstr[g_mspos+i];
155+ }
156+ g_mspos+=i;
157+ return ret;
158+}
159+
160+void init_music(){
161+ // Use Timer3 and OC4 for sound.
162+ RPB13R=5; //Use RPB13 for OC4
163+ OC4R=0;
164+ OC4CON=0x000b; // Timer3, toggle mode
165+ OC4CONSET=0x8000;// Start OC4
166+ T3CON=0x0050; // Prescaller: 1:32 (1.8 MHz), not yet started
167+
168+ // Timer4 is used to intterupt every 1/60 sec, just after NTSC view.
169+ T4CON=0x0040; // Prescaller: 1:16
170+ PR4=59473; // 3632*262/16-1
171+ // Timer 4 interruption, IPL3
172+ IPC4bits.T4IP=3;
173+ IPC4bits.T4IS=0;
174+ IFS0bits.T4IF=0;
175+ IEC0bits.T4IE=1;
176+ // Wait until end of NTSC view.
177+ while(!drawing);
178+ while(drawing);
179+ T4CONSET=0x8000; // Start timer 4.
180+
181+ // Initializations for music/sound.
182+ g_qvalue=160; // Q: 1/4=90
183+ g_lvalue=20; // L: 1/8
184+ g_tones=(int*)&(g_keys[49]); // C major
185+ g_musicstart=g_musicend=g_musicwait=g_soundstart=g_soundend=g_soundwait=g_soundrepeat=0;
186+}
187+
188+void musicSetL(){
189+ // Set length of a character.
190+ // Syntax: L:n/m, where n and m are numbers.
191+ int n,m;
192+ n=musicGetNum();
193+ g_mspos++;
194+ m=musicGetNum();
195+ g_lvalue=g_qvalue*n/m;
196+}
197+
198+void musicSetQ(){
199+ int i;
200+ // Syntax: Q:1/4=n, where n is number.
201+ // Skip "1/4="
202+ for(i=0;g_mstr[g_mspos+i]!='=';i++);
203+ g_mspos+=i+1;
204+ i=musicGetNum();
205+ if (i<48) { g_qvalue=320; /* 1/4=45 */ }
206+ else if (i<53) { g_qvalue=288; /* 1/4=50 */ }
207+ else if (i<60) { g_qvalue=256; /* 1/4=56 */ }
208+ else if (i<70) { g_qvalue=224; /* 1/4=64 */ }
209+ else if (i<83) { g_qvalue=192; /* 1/4=75 */ }
210+ else if (i<102) { g_qvalue=160; /* 1/4=90 */ }
211+ else if (i<132) { g_qvalue=128; /* 1/4=113 */ }
212+ else if (i<188) { g_qvalue=96; /* 1/4=150 */ }
213+ else { g_qvalue=64; /* 1/4=225 */ }
214+ g_lvalue=g_qvalue>>3;
215+}
216+
217+void musicSetK(){
218+ // Syntax: K:xxx
219+ if (!strncmp((char*)&(g_mstr[g_mspos]),"A#m",3)) {
220+ g_mspos+=3;
221+ g_tones=(int*)&(g_keys[0]);
222+ return;
223+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"D#m",3)) {
224+ g_mspos+=3;
225+ g_tones=(int*)&(g_keys[7]);
226+ return;
227+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"G#m",3)) {
228+ g_mspos+=3;
229+ g_tones=(int*)&(g_keys[14]);
230+ return;
231+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"C#m",3)) {
232+ g_mspos+=3;
233+ g_tones=(int*)&(g_keys[21]);
234+ return;
235+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"F#m",3)) {
236+ g_mspos+=3;
237+ g_tones=(int*)&(g_keys[28]);
238+ return;
239+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Bbm",3)) {
240+ g_mspos+=3;
241+ g_tones=(int*)&(g_keys[84]);
242+ return;
243+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Ebm",3)) {
244+ g_mspos+=3;
245+ g_tones=(int*)&(g_keys[91]);
246+ return;
247+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Abm",3)) {
248+ g_mspos+=3;
249+ g_tones=(int*)&(g_keys[98]);
250+ return;
251+ }
252+ if (!strncmp((char*)&(g_mstr[g_mspos]),"C#",2)) {
253+ g_mspos+=2;
254+ g_tones=(int*)&(g_keys[0]);
255+ return;
256+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"F#",2)) {
257+ g_mspos+=2;
258+ g_tones=(int*)&(g_keys[7]);
259+ return;
260+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Bm",2)) {
261+ g_mspos+=2;
262+ g_tones=(int*)&(g_keys[35]);
263+ return;
264+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Em",2)) {
265+ g_mspos+=2;
266+ g_tones=(int*)&(g_keys[42]);
267+ return;
268+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Am",2)) {
269+ g_mspos+=2;
270+ g_tones=(int*)&(g_keys[49]);
271+ return;
272+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Dm",2)) {
273+ g_mspos+=2;
274+ g_tones=(int*)&(g_keys[56]);
275+ return;
276+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Gm",2) || !strncmp((char*)&(g_mstr[g_mspos]),"Bb",2)) {
277+ g_mspos+=2;
278+ g_tones=(int*)&(g_keys[63]);
279+ return;
280+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Cm",2) || !strncmp((char*)&(g_mstr[g_mspos]),"Eb",2)) {
281+ g_mspos+=2;
282+ g_tones=(int*)&(g_keys[70]);
283+ return;
284+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Fm",2) || !strncmp((char*)&(g_mstr[g_mspos]),"Ab",2)) {
285+ g_mspos+=2;
286+ g_tones=(int*)&(g_keys[77]);
287+ return;
288+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Db",2)) {
289+ g_mspos+=2;
290+ g_tones=(int*)&(g_keys[84]);
291+ return;
292+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Gb",2)) {
293+ g_mspos+=2;
294+ g_tones=(int*)&(g_keys[91]);
295+ return;
296+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Cb",2)) {
297+ g_mspos+=2;
298+ g_tones=(int*)&(g_keys[98]);
299+ return;
300+ }
301+ switch(g_mstr[g_mspos]){
302+ case 'B':
303+ g_mspos++;
304+ g_tones=(int*)&(g_keys[14]);
305+ return;
306+ case 'E':
307+ g_mspos++;
308+ g_tones=(int*)&(g_keys[21]);
309+ return;
310+ case 'A':
311+ g_mspos++;
312+ g_tones=(int*)&(g_keys[28]);
313+ return;
314+ case 'D':
315+ g_mspos++;
316+ g_tones=(int*)&(g_keys[35]);
317+ return;
318+ case 'G':
319+ g_mspos++;
320+ g_tones=(int*)&(g_keys[42]);
321+ return;
322+ case 'C':
323+ g_mspos++;
324+ g_tones=(int*)&(g_keys[49]);
325+ return;
326+ case 'F':
327+ g_mspos++;
328+ g_tones=(int*)&(g_keys[56]);
329+ return;
330+ default:
331+ err_music(g_mstr);
332+ break;
333+ }
334+}
335+void musicSetM(){
336+ // Currently do nothing
337+ musicGetNum();
338+ musicGetNum();
339+}
340+
341+void set_sound(unsigned long* data){
342+ int sound;
343+ int len;
344+ int pos;
345+ int datalen;
346+ IEC0bits.T4IE=0; // Stop interruption, first.
347+ // Initialize
348+ g_soundrepeat=g_soundstart=g_soundend=0;
349+ pos=0;
350+ do {
351+ while(data[1]!=0x00000020) data++; // Seek DATA statement
352+ datalen=(data[0]&0x00007FFF)-1; // Use bgezal statement containing data length.
353+ data+=2;
354+ while(0<datalen){
355+ datalen--;
356+ len=data[0]>>16;
357+ sound=data[0]&0x0000FFFF;
358+ data++;
359+ if (len) {
360+ // Shift tone if graphic is used
361+ if (g_use_graphic) {
362+ // MUL_15 instead of MUL_16 for CPU clock.
363+ // sound=sound*15/16
364+ sound-=(sound+7)>>4;
365+ }
366+ g_sound[pos]=sound-1;
367+ g_soundlen[pos]=len;
368+ pos++;
369+ if (32<pos) {
370+ err_music("Sound data too long.");
371+ return;
372+ }
373+ } else {
374+ g_soundrepeat=sound;
375+ break;
376+ }
377+ }
378+ } while(len);
379+ g_soundend=pos;
380+ g_soundwait=g_soundlen[0];
381+ IEC0bits.T4IE=1; // Restart interrupt.
382+}
383+
384+void set_music(char* str){
385+ char b;
386+ unsigned long tone,tonenatural;
387+ int len;
388+ g_mstr=str;
389+ g_mspos=0;
390+ while(0<(b=g_mstr[g_mspos])){
391+ if (g_mstr[g_mspos+1]==':') {
392+ // Set property
393+ g_mspos+=2;
394+ switch(b){
395+ case 'L':
396+ musicSetL();
397+ break;
398+ case 'Q':
399+ musicSetQ();
400+ break;
401+ case 'K':
402+ musicSetK();
403+ break;
404+ case 'M':
405+ musicSetM();
406+ break;
407+ default:
408+ err_music(str);
409+ break;
410+ }
411+ } else if ('A'<=b && b<='G' || 'a'<=b && b<='g' || b=='z') {
412+ g_mspos++;
413+ if (b=='z') {
414+ tone=0;
415+ } else if (b<='G') {
416+ tone=g_tones[b-'A'];
417+ tonenatural=g_keys[b-'A'+49];
418+ } else {
419+ tone=g_tones[b-'a']>>1;
420+ tonenatural=g_keys[b-'a'+49]>>1;
421+ }
422+ // Check "'"s
423+ while(g_mstr[g_mspos]=='\''){
424+ g_mspos++;
425+ tone>>=1;
426+ }
427+ // Check ","s
428+ while(g_mstr[g_mspos]==','){
429+ g_mspos++;
430+ tone<<=1;
431+ tonenatural<<=1;
432+ }
433+ // Check "^","=","_"
434+ switch(g_mstr[g_mspos]){
435+ case '^':
436+ g_mspos++;
437+ tone=toneSharp(tone);
438+ break;
439+ case '_':
440+ g_mspos++;
441+ tone=toneFlat(tone);
442+ break;
443+ case '=':
444+ g_mspos++;
445+ tone=tonenatural;
446+ break;
447+ default:
448+ break;
449+ }
450+ // Check number for length
451+ b=g_mstr[g_mspos];
452+ if ('0'<=b && b<='9') {
453+ len=g_lvalue*musicGetNum();
454+ } else {
455+ len=g_lvalue;
456+ }
457+ if (g_mstr[g_mspos]=='/') {
458+ g_mspos++;
459+ len=len/musicGetNum();
460+ }
461+ // Shift tone if graphic is used
462+ if (g_use_graphic) {
463+ // MUL_15 instead of MUL_16 for CPU clock.
464+ // tone=tone*15/16
465+ tone-=(tone+7)>>4;
466+ }
467+ // Update music value array
468+ IEC0bits.T4IE=0; // Stop interruption, first.
469+ if (g_musicstart==g_musicend) {
470+ g_musicwait=len;
471+ }
472+ g_music[g_musicend]=(tone-1)&0x0000FFFF;
473+ g_musiclen[g_musicend]=len;
474+ g_musicend++;
475+ g_musicend&=31;
476+ IEC0bits.T4IE=1; // Restart interruption.
477+ } else {
478+ err_music(str);
479+ }
480+ // Go to next character
481+ while(0<g_mstr[g_mspos] && g_mstr[g_mspos]<=0x20 || g_mstr[g_mspos]=='|') g_mspos++;
482+ }
483+}
\ No newline at end of file
--- mips/tags/zoea1.00/help.txt (nonexistent)
+++ mips/tags/zoea1.00/help.txt (revision 148)
@@ -0,0 +1,585 @@
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+CURSOR x,y
41+ カーソル位置指定。
42+CDATA xxx[,yyy[,zzz[...]]]
43+ データー列を8ビット整数値で指定する。
44+DATA xxx[,yyy[,zzz[...]]]
45+ データー列を整数値もしくは文字列で指定する。
46+DIM xxx [, yyy [, zzz [, ... ]]]
47+ 整数型もしくは浮動小数点型の配列を割り当てる。
48+ xxx,yyy,zzzは、例えば「A(10)」のように記述する。この場合、A(0)から
49+ A(10)までの11個の整数型変数が確保される。浮動小数点型配列の場合は、
50+ 「A#(10)」の様に記述する。多次元配列も、宣言することが出来る。
51+DO WHILE x
52+LOOP
53+ x が0以外の場合、DO文からLOOP文までのステートメントを繰り返し実行する。
54+DO UNTIL x
55+LOOP
56+ x が0の場合、DO文からLOOP文までのステートメントを繰り返し実行する。
57+DO
58+LOOP WHILE x
59+ DO文からLOOP文までのステートメントを実行し、x が0以外の場合、繰り返す。
60+DO
61+LOOP UNTIL x
62+ DO文からLOOP文までのステートメントを実行し、x が0の場合、繰り返す。
63+DRAWCOUNT
64+ DRAWCOUNT値を指定する。DRAWCOUNT値に付いては、DRAWCOUNT()関数を
65+ 参照。
66+END
67+ BASICプログラムを停止する。
68+EXEC x[,y[,z[...]]]
69+ 機械語を実行する。ただし、x,y,zは32ビット整数値。
70+FOR x=yyy TO zzz [ STEP www ]
71+NEXT
72+ yyyで示された計算結果をxに代入し、xの値がzzzになるまで次のNEXT文
73+ までのステートメントを、繰り返し実行する。繰り返しのたび、xの値は
74+ wwwずつ増加する(省略された場合は1ずつ)。「NEXT」の次に何も記述
75+ しないことに注意。
76+GOSUB xxx [, yyy [, zzz [, ... ]]]
77+ 現在の実行位置を記憶し、xxx行目(もしくはラベル)に移動する。yyy, zzz
78+ 等は、サブルーチンに引き継がれる引数(ARGS()関数を参照)。
79+GOTO xxx
80+ xxx行目(もしくはラベル)に移動する。
81+IF xまたはx# THEN yyy [ ELSE zzz ]
82+ xが0以外のとき、yyyを、0のときzzzを実行。yyyおよびzzzは、複数のステート
83+ メントを「:」で挟んで記述可能。
84+IF xまたはx# THEN
85+xxx
86+[ELSEIF yまたはy# THEN
87+yyy]
88+[ELSE
89+zzz]
90+ENDIF
91+ xが0以外の時xxxを、それ以外で且つyが0以外の時(記述された場合)yyyを、
92+ それ以外の場合にzzzを実行。ELSEIFステートメントは、複数記述可。各行で、
93+ THENステートメントの次には何も記入しないことに注意。
94+LABEL xxx
95+ GOTO/GOSUBのジャンプ先を登録する。xxxは、英数字6文字以内の文字列。
96+[LET] x=yyy
97+ yで示された計算結果を、x(整数型変数)に代入する。「LET」は省略可。
98+[LET] x#=yyy
99+ yで示された計算結果を、x(不動州数点方型変数)に代入する。「LET」は省略可。
100+[LET] x$=yyy
101+ yyyで示された文字列(もしくは連結結果;連結演算子は「+」)を、x$に
102+ 代入する。「LET」は省略可。
103+MUSIC x$
104+ BGMを演奏する。詳細は、下記<MUSIC>の項を参照。
105+VAR xxx [, yyy [, zzz [, ... ]]]
106+ サブルーチン内で使う、ローカル変数を指定する。xxx, yyy等は、A-Zの
107+ アルファベットで指定する。
108+WHILE x
109+WEND
110+ x が0以外の場合、WHILE文からWEND文までのステートメントを繰り返し実行する。
111+PALETTE n,r,g,b
112+ パレット指定。
113+PCG x,y,z
114+ ASCIIコードがxの文字の表示キャラクターを変更する。y,zは、キャラク
115+ ターデーター。詳細は、下記<PCG>の項を参照。
116+POKE x,y
117+ xで示される物理的アドレスに、yで示される値(1バイト値)を書き込む。
118+PRINT [ xまたはx$またはx# [ ,または; [ yまたはy$またはy# [ ... ]]]]
119+ ディスプレイに、整数値または文字列を表示する。「;」を使用した場
120+ 合、次の表示が続けて行われる。「,」を使用した場合、10文字ずつ
121+ に区切って表示される。どちらも使用しない場合、次の表示は行を変え
122+ て行われる。
123+REM xxx
124+ 何も実行しない
125+RESTORE xxx
126+ DATA読み出し開始位置を指定。xxxは行番号もしくはラベル。
127+RETURN
128+ 最後に実行されたGOSUB文の次のステートメントに移動する。戻り値を指
129+ 定することがができる。この場合の戻り値はGOSUB()関数にて取得が可能。
130+SCROLL x,y
131+ 画面を横方向、もしくは縦方向(斜めも可)に動かす。動かす方向と大きさ
132+ は、x, yでそれぞれ、横方向の移動度、縦方向の移動度として指定する。
133+SOUND xxx
134+ 効果音を再生する。詳細は、下記<SOUND>の項を参照。xxxは行番号もしく
135+ はラベル。
136+SYSTEM x , y
137+ 様々なシステム値の設定を行なう。<SYSTEM>の項を参照。
138+USEGRAPHIC [x]
139+ グラフィックディスプレイを使用、もしくは使用停止する。x=0で使用停止、
140+ x=1で使用、x=2で画面とパレットをクリアーして使用、x=3でグラフィック領
141+ 域を確保するが表示はキャラクターディスプレイのまま。ただし、グラフィッ
142+ クディスプレイ未使用の状態でx=0の場合は、領域を確保する。xを省略した場
143+ 合は、x=1と同じ。
144+USEPCG [x]
145+ PCGを使用、もしくは使用停止する。x=0で使用停止、x=1で使用、x=2で
146+ キャラクターをリセットして使用。xを省略した場合は、x=1と同じ。
147+
148+WAIT x
149+ xで示された時間、プログラムの実行を停止する。xが60の場合、約1秒間
150+ 停止。
151+
152+<グラフィック関連命令>
153+
154+BOXFILL [x1,y1],x2,y2[,c]
155+ 座標(x1,y1),(x2,y2)を対角線とするカラーcで塗られた長方形を描画。
156+CIRCLE [x,y],r[,c]
157+ 座標(x,y)を中心に、半径r、カラーcの円を描画。
158+CIRCLEFILL [x,y],r[,c]
159+ 座標(x,y)を中心に、半径r、カラーcで塗られた円を描画。
160+GCLS
161+ 画面クリアー。
162+GCOLOR c
163+ それぞれの命令で、cを省略した場合の色を指定。
164+GPALETTE n,r,g,b
165+ パレット指定。
166+GPRINT [x,y],c,bc,s$
167+ 座標(x,y)にカラーcで文字列s$を表示、bc:背景色(負数の場合背景色指定なし)。
168+LINE [x1,y1],x2,y2[,c]
169+ 座標(x1,y1)から(x2,y2)にカラーcで線分を描画。
170+POINT x,y
171+ グラフィック現在位置を、設定する。
172+PSET [x,y][,c]
173+ 座標(x,y)の位置にカラーcで点を描画。
174+PUTBMP [x,y],m,n,bbb
175+ 横m*縦nドットのキャラクター(bbbで指定)を座標(x,y)に表示。
176+ サイズm*nの配列bmpに、単純にカラー番号を並べる。
177+ ただし、カラーが0の部分は透明色として扱う。ただし、bbbはラベル名もし
178+ くは配列へのポインター。
179+
180+<整数型関数>
181+以下、x, y, zは整数値を、x$, y$, z$は文字列を指します。[ ]は省略可能である事
182+を示します。
183+
184+ABS(x)
185+ xの絶対値を返す。
186+ARGS(x)
187+ サブルーチン中で、GOSUBに渡されたx番目の引数を整数値として取り出す。
188+ASC(x$)
189+ 文字列の最初の一文字の、アスキーコードを返す。
190+CREAD()
191+ DATA文の後から、一つずつデーター(8ビット整数値)を読み出す。「READ()」
192+ 関数も参照。
193+DRAWCOUNT()
194+ DRAWCOUNT値を得る。DRAWCOUNTは16ビット整数値で、1/60秒ごとに1ずつ
195+ 増える。
196+GCOLOR(x,y)
197+ グラフィック座標(x,y)の表示中パレット番号を返す。
198+GOSUB(xxx [, y [, z [, ... ]]])
199+ GOSUB命令と同じだが、戻り値(RETURNを参照)を得ることが出来る。xxxは、
200+ ラベルもしくは行番号。。yyy, zzz 等は、サブルーチンに引き継がれる引数(
201+ ARGS()関数を参照)。
202+INKEY([x])
203+ xを指定しない場合、現在押されているキーのASCII値を返す。押されていな
204+ い場合は、0。ASCII値でxを指定した場合、そのキーが押されているかどう
205+ かを返す。
206+INT(x#)
207+ 実数値x#を整数値に変換して返す。
208+KEYS([x])
209+ キー入力を得る。xの値は以下の通り。xを指定しない場合は、x=63と同じ。
210+ KEYUP: 1
211+ KEYDOWN: 2
212+ KEYLEFT: 4
213+ KEYRIGHT: 8
214+ KEYSTART: 16
215+ KEYFIRE: 32
216+LEN(x$)
217+ 文字列の長さを返す。
218+MUSIC()
219+ BGMの演奏の残り数を返す。
220+NOT(x)
221+ x=0の場合に1を、そうでない場合に0を返す。
222+PEEK(x)
223+ xで示される物理アドレスから1バイト読み取り、返す。
224+READ()
225+ DATA文の後から、一つずつデーター(32ビット整数値)を読み出す。「CREAD()」
226+ 関数も参照。
227+RND()
228+ 0から32767までの擬似乱数を返す。
229+SGN(x)
230+ xの符号(-1, 0, または1)を返す。
231+STRNCMP(x$,y$,z)
232+ 2つの文字列のうちz文字分を比較し、結果を返す。同じ文字列の場合は0。
233+SYSTEM(x)
234+ 様々なシステム値を、整数値で返す。「<システム変数>」の項を参照。
235+TVRAM([x])
236+ ビデオRAMのx番目の内容を、バイト値で返す。xを省略した場合、ビデオ
237+ RAMの開始位置の物理アドレスを返す。
238+VAL(x$)
239+ 10進数もしくは16進数文字列としてのx$の値を、整数値で返す。
240+
241+<浮動小数点型関数>
242+ACOS#(x#)
243+ x# の逆余弦を実数値で返す。
244+ARGS#(x)
245+ サブルーチン中で、GOSUBに渡されたx番目の引数を実数値として取り出す。
246+ASIN#(x#)
247+ x# の逆正弦を実数値で返す。
248+ATAN#(x#)
249+ x# の逆正接を実数値で返す。
250+CEIL#(x#)
251+ x# 以上の最小の整数を実数値で返す。
252+COS#(x#)
253+ x# の余弦を実数値で返す。
254+COSH#(x#)
255+ x# の双曲線余弦を実数値で返す。
256+EXP#(x#)
257+ eを底とする x# の指数関数値を実数値で返す。
258+FABS#(x#)
259+ x# の絶対値を実数値で返す。
260+FLOAT#(x)
261+ 整数値 x を浮動小数点型実数値に変換して返す。
262+FLOOR#(x#)
263+ x# 以下の最大の整数を実数値で返す。
264+FMOD#(x#,y#)
265+ x# を y# で割った剰余を実数値で返す。
266+GOSUB#(xxx [, y [, z [, ... ]]])
267+ GOSUB命令と同じだが、戻り値(RETURNを参照)を得ることが出来る。xxxは、
268+ ラベルもしくは行番号。。yyy, zzz 等は、サブルーチンに引き継がれる引数(
269+ ARGS()関数を参照)。
270+LOG#(x#)
271+ x# の自然対数を実数値で返す。
272+LOG10#(x#)
273+ x# の常用対数を実数値で返す。
274+MODF#(x#)
275+ x# の小数部を実数値で返す。
276+PI#
277+ 3.141593を返す。
278+POW#(x#,y#)
279+ x# の y# 乗を実数値で返す。
280+SIN#(x#)
281+ x# の正弦を実数値で返す。
282+SINH#(x#)
283+ x# の双曲線正弦を実数値で返す。
284+SQRT#(x#)
285+ x# の平方根を実数値で返す。
286+TAN#(x#)
287+ x# の正接を実数値で返す。
288+TANH#(x#)
289+ x# の双曲線正接を実数値で返す。
290+VAL#(x$)
291+ 10進数文字列としてのx$の値を、実数値で返す。
292+
293+<文字列型関数>
294+A$(x [,y])など
295+ xの値が0の場合、文字列全体を返す。
296+ xの値が正の場合、xで示される位置より右側の文字列を返す。
297+ xの値が負のとき、文字列の右側x文字を返す。
298+ yが指定された場合、y文字分の文字列を返す。
299+ARGS$(x)
300+ サブルーチン中で、GOSUBに渡されたx番目の引数を文字列として取り出す。
301+CHR$(x)
302+ xをアスキーコードとする文字を返す。
303+DEC$(x)
304+ xの値を、10進数の文字列として返す。
305+FLOAT$(x#)
306+ 実数値x#を、10進数の文字列として返す。
307+GOSUB$(xxx [, y [, z [, ... ]]])
308+ GOSUB命令と同じだが、戻り値(RETURNを参照)を文字列として得ることが出来る。
309+ xxxは、ラベルもしくは行番号。。yyy, zzz 等は、サブルーチンに引き継がれる引数
310+ (ARGS()関数を参照)。
311+HEX$(x [,y])
312+ xの値を、16進数の文字列として返す。yが指定された場合、yバイト長の
313+ 文字列になる。
314+INPUT$()
315+ 文字列入力状態になり、入力が終了すると(Enterが押されると)文字列を返す。
316+SPRINTF$(x$,y#)
317+ x$で示される書式に従って、実数y#の内容を文字列として返す。
318+SYSTEM$(x)
319+ 様々なシステム値を、文字列で返す。「<システム変数>」の項を参照。
320+READ$()
321+ DATA文の後から、一つずつ文字列データーを読み出す。
322+
323+<整数演算子>
324+-x
325+ 符号を反転
326+x + y
327+ 整数加算
328+x - y
329+ 整数減算
330+x * y
331+ 整数乗算
332+x / y
333+ 整数除算
334+x % y
335+ 整数剰余
336+x >> y
337+ xの値をyビット右シフト
338+x << y
339+ xの値をyビット左シフト
340+x = y
341+ 2つの整数値が等しい場合に1、そうでないときに0
342+x != y
343+ 2つの整数値が等しい場合に0、そうでないときに1
344+x < y
345+ xがyより小さい場合に1、そうでないときに0
346+x <= y
347+ xがyより小さいか等しい場合に1、そうでないときに0
348+x > y
349+ xがyより多きい場合に1、そうでないときに0
350+x >= y
351+ xがyより多きいか等しい場合に1、そうでないときに0
352+x AND y
353+ xとyの値のビットごとの AND(論理積でないことに注意)
354+x OR y
355+ xとyの値のビットごとの OR
356+x XOR y
357+ xとyの値のビットごとの XOR
358+
359+なお、整数演算子の優先順位は、優先度が高いものから以下の順です。
360+
361++ - (単項演算子)
362+* / %
363++ - (加算・減算)
364+<< >>
365+< <= > >=
366+= !=
367+XOR
368+AND
369+OR
370+
371+<文字列演算子>
372+x$ + y$
373+ 文字列の連結
374+
375+<浮動小数点型演算子>
376+-x#
377+ 符号を反転
378+x# + y#
379+ 実数加算
380+x# - y#
381+ 実数減算
382+x# * y#
383+ 実数乗算
384+x# / y#
385+ 実数除算
386+x# = y#
387+ 2つの実数値が等しい場合に1、そうでないときに0
388+x# != y#
389+ 2つの実数値が等しい場合に0、そうでないときに1
390+x# < y#
391+ xがyより小さい場合に1、そうでないときに0
392+x# <= y#
393+ xがyより小さいか等しい場合に1、そうでないときに0
394+x# > y#
395+ xがyより多きい場合に1、そうでないときに0
396+x# >= y#
397+ xがyより多きいか等しい場合に1、そうでないときに0
398+x# AND y#
399+ xとyの値の論理積(ビットごとの AND でないことに注意)
400+x# OR y#
401+ xとyの値の論理和(ビットごとの OR でないことに注意)
402+
403+なお、実数演算子の優先順位は、優先度が高いものから以下の順です。
404+
405++ - (単項演算子)
406+* /
407++ - (加算・減算)
408+< <= > >=
409+= !=
410+AND
411+OR
412+
413+<MUSIC>
414+MUSIC命令では、BGM用のデーターを文字列で指定します。文字列の書式は、ABC
415+notationに準拠しています。ただし、すべての記法が使えるわけではありません。
416+なお、キーや速度などのデフォルト設定値は以下の通りです。
417+
418+Q: 1/4=90
419+L: 1/8
420+K: C
421+
422+BGM演奏時に一度に設定できる音の数は、31迄です。これを超えて音楽を再生したい
423+場合は、MUSIC()関数の戻り値を調べ、その値が十分小さくなってから、次のMUSIC命
424+令を実行するようにします。
425+
426+添付のmusic.basに、使い方に関するサンプルがありますので、参考にして下さい。
427+
428+<SOUND>
429+SOUND命令では、DATA列のデーターを、行番号もしくはラベルで指定します。SOUND命
430+令による効果音再生中は、BGMは再生されません。また、前の効果音が終わる前に次
431+のSOUND命令を実行すると、前の効果音の再生は停止し、新しい効果音がすぐに再生
432+されます。
433+
434+DATA列では、32ビット整数値として、交換音を表現します。この整数値の下位16
435+ビットは周波数の指定です。2048が440Hz(ラの音)に対応します。値が大きくなるほ
436+ど、より低い音が出ます。上位16ビットは、音の長さです。1が、1/60秒に相当し
437+ます。最後に、65535以下の値で、効果音の繰り返し回数を指定します。これらのデー
438+ターの数は、32を超えないようにして下さい。
439+
440+添付のsound.basに、使い方に関するサンプルがありますので、参考にして下さい。
441+
442+<PCG>
443+PCG(Programmable Character Generator)を用いると、ASCIIコードごとにフォント
444+を指定して、疑似グラフィックスとして表示させることが出来ます。使用する場合
445+は、まず
446+
447+USEPCG
448+
449+とします。フォントの変更は、PCGステートメントを用いて、
450+
451+PCG 0x80,0x80402010,0x08040201
452+
453+の様に設定します。この例では、ASCIIコード0x80の文字のフォントを設定してい
454+て、バックスラッシュの様な記号(左上から右下に向かう斜め線)が表示されるよう
455+になります。PCGの利用を停止し、オリジナルのフォントに戻す場合は、
456+
457+USEPCG 0
458+
459+とします。再度PCGを使用したい場合は、
460+
461+USEPCG
462+
463+として下さい。先に設定したフォントデーターが、復活します。なお、先に設定し
464+たフォントデーターを破棄してPCGの使用を始めたい場合は、
465+
466+USEPCG 2
467+
468+として下さい。
469+
470+<システム変数>
471+SYSTEM関数及びSYSTEMステートメントを用いて、各種システム情報をやりとりするこ
472+とが出来ます。
473+
474+SYSTEM$(0)
475+ MachiKania バージョン文字列、"Zoea"を返す。
476+SYSTEM$(1)
477+ MachiKania バージョン文字列、"1.0"等を返す。
478+SYSTEM$(2)
479+ BASIC バージョン文字列、"KM-1200"等を返す。
480+SYSTEM$(3)
481+ 現在実行中のHEXファイル名、"ZOEA.HEX"等を返す。
482+SYSTEM(20)
483+ キャラクターディスプレイ横幅を返す。
484+SYSTEM(21)
485+ キャラクターディスプレイ縦幅を返す。
486+SYSTEM(22)
487+ グラフィックディスプレイ横幅を返す。
488+SYSTEM(23)
489+ グラフィックディスプレイ横幅を返す。
490+SYSTEM(24)
491+ キャラクターディスプレイ用の指定色を返す。
492+SYSTEM(25)
493+ グラフィックディスプレイ用の指定色を返す。
494+SYSTEM(26)
495+ キャラクターディスプレイの、現在のX位置を返す。
496+SYSTEM(27)
497+ キャラクターディスプレイの、現在のY位置を返す。
498+SYSTEM(28)
499+ グラフィックディスプレイの、現在のX位置を返す。
500+SYSTEM(29)
501+ グラフィックディスプレイの、現在のY位置を返す。
502+SYSTEM(40)
503+ PS/2キーボードを使用中かどうかを返す。
504+SYSTEM(41)
505+ PS/2キーボード情報、vkeyを返す。
506+SYSTEM(42)
507+ PS/2キーボード情報、lockkeyを返す。
508+SYSTEM(43)
509+ PS/2キーボード情報、keytypeを返す。
510+SYSTEM(100)
511+ 変数格納領域(g_var_mem)へのポインターを返す。
512+SYSTEM(101)
513+ 乱数シードへのポインターを返す。
514+SYSTEM(102)
515+ キャラクターディスプレイ領域(TVRAM)へのポインターを返す。
516+SYSTEM(103)
517+ フォント領域へのポインターを返す。
518+SYSTEM(104)
519+ PCGフォント領域へのポインターを返す。
520+SYSTEM(105)
521+ グラフィックディスプレイ領域へのポインターを返す。
522+SYSTEM 200,x
523+ ディスプレイの表示を停止(xが0のとき)、もしくは開始(xが0以外の時)する。
524+
525+<ヒント>
526+FOR-NEXTループ、WHILE-WENDループ、DO-LOOPループの途中で、GOTO文でループの
527+外に飛んだり、RETURN文を実行したりすると、予期せぬ結果(機器のリセット等)を
528+引き起こします。ただし、GOSUB文でサブルーチンを呼んだり、別のループをネスト
529+して使う事は可能です。
530+
531+ON GOTO分やON GOSUB文はサポートしていません。ただし、例えば次のように記述す
532+ることで、同様の動作をさせることは可能です。
533+ GOSUB 10000+A
534+ ....
535+ 10000 PRINT "A=0" : RETURN
536+ 10001 PRINT "A=1" : RETURN
537+ 10002 PRINT "A=2" : RETURN
538+
539+一行中で連続して文字列を扱うと、"String too complexed"というエラーがでて、
540+停止することがあります。この場合は、文字列を扱う命令を独立した行するか、文
541+字列関連の演算を幾つかのステップに分けて、それぞれ1行ずつの記述にして試し
542+てみて下さい。
543+
544+<バージョン履歴>
545+・KM-1200 2016年8月公開。
546+ 1.グラフィックディスプレイ機能および、関連のステートメント群を追加。
547+ 2.浮動小数点演算機能、及び、算術演算関数群を追加。
548+ 3.VAR, BREAK, SYSTEMステートメントを追加。
549+ 4.DO-LOOP, WHILE-WENDループ構造文を追加。
550+ 5.IF THEN - ELSEIF - ELSE - ENDIFによる、複数行での条件分岐表現を追加。
551+ 6.GOSUBステートメント及びGOSUB()関数に第二以降の引数を指定出来る様にし、
552+   サブルーチン中でARGS()関数により取り出せるようにした。
553+ 7.8ビット整数型を扱うCDATAステートメントとCREAD()関数を追加。
554+ 8.DATAステートメントで文字列を扱える様にし、READ$()で読めるようにした。
555+ 9.多次元配列をサポート。
556+ 10.例外発生時に、情報を表示するようにした。
557+ 11.FOR-NEXTループに於いて、TO値に一致する時だけではなく、値を超えた場合
558+   でもループを抜けるようにした。
559+ 12.MUSICステートメント用のスクリプトにエラーがある際、エラー発生行が正し
560+   く表示されない不具合を修正。
561+ 13.ビットシフト演算子を、追加。
562+
563+・KM-1120 2016年2月公開。
564+ 1.PCG機能を追加。
565+ 2.SCROLL命令を追加。
566+ 3.WAIT命令を追加。
567+ 4.「Ctrl+Break」キーによる実行停止に対応。
568+ 5.FOR無しでNEXTを実行した場合、GOSUB無しでRETURNを実行した場合にエラー
569+   を表示して停止するようにした。
570+
571+・Ver 1.1.0 (KM-1110) 2015年12月公開。
572+ 1.2015年11月21日に変更されたPIC32TVGSの仕様に対応。
573+ 2.PS/2キーボードに対応。
574+ 3.INKEY() INPUT$() VAL() DEC$() の4つの関数を追加。
575+ 4.TVRAM() ASC() PEEK()が、0x80-0xFFの値に関して負の数を返していた不具合
576+   を修正。
577+ 5.DIMステートメントにより配列を定義した際、すべての要素がゼロになるよう
578+   にした。
579+ 6.単項演算子、「-」「+」を追加。
580+ 7.LABEL定義されていない飛び先にGOTOするとリセットされる不具合を修正。
581+ 8.同一のLABELを複数回使用している場合に、コンパイルエラーが出るように修
582+   正。
583+ 9.引数を持たないPRINT文に対応。
584+
585+・Ver 1.0.5 (KM-1100) 最初の正規公開バージョン。
--- mips/tags/zoea1.00/run.c (nonexistent)
+++ mips/tags/zoea1.00/run.c (revision 148)
@@ -0,0 +1,139 @@
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+ // Initialize SD card file system
56+ err=init_file(buff,appname);
57+ if (err) {
58+ setcursorcolor(COLOR_ERRORTEXT);
59+ printstr("Can't Open ");
60+ printstr(appname);
61+ printchar('\n');
62+ return -1;
63+ }
64+
65+ // Initialize parameters
66+ g_pcg_font=0;
67+ g_use_graphic=0;
68+ g_graphic_area=0;
69+ clearscreen();
70+ setcursor(0,0,7);
71+
72+ printstr("BASIC "BASVER"\n");
73+ wait60thsec(15);
74+ // Initialize music
75+ init_music();
76+
77+ printstr("Compiling...");
78+
79+ // Compile the file
80+ err=compile_file();
81+ close_file();
82+ if (err) {
83+ // Compile error
84+ printstr(err);
85+ printstr("\nAround: '");
86+ for(i=0;i<5;i++){
87+ printchar(g_source[g_srcpos-2+i]);
88+ }
89+ printstr("' in line ");
90+ printdec(g_line);
91+ printstr("\n");
92+ for(i=g_srcpos;0x20<=g_source[i];i++);
93+ g_source[i]=0x00;
94+ for(i=g_srcpos;0x20<=g_source[i];i--);
95+ printstr(g_source+i);
96+ return g_fileline;
97+ }
98+
99+ // Link
100+ err=link();
101+ if (err) {
102+ // Link error
103+ printstr(err);
104+ printstr(resolve_label(g_label));
105+ return -2;
106+ }
107+
108+ // All done
109+ printstr("done\n");
110+ if(test) return 0; //コンパイルのみの場合
111+ wait60thsec(15);
112+
113+ // Initialize the other parameters
114+ // Random seed
115+ g_rnd_seed=2463534242;
116+ // Clear variables
117+ for(i=0;i<ALLOC_BLOCK_NUM;i++){
118+ g_var_mem[i]=0;
119+ g_var_size[i]=0;
120+ }
121+ // Clear key input buffer
122+ for(i=0;i<256;i++){
123+ ps2keystatus[i]=0;
124+ }
125+ // Reset data/read.
126+ reset_dataread();
127+
128+ // Assign memory
129+ set_free_area((void*)(g_object+g_objpos),(void*)(&RAM[RAMSIZE]));
130+ // Execute program
131+ // Start program from the beginning of RAM.
132+ // Work area (used for A-Z values) is next to the object code area.
133+ start_program((void*)(&(RAM[0])),(void*)(&g_var_mem[0]));
134+ printstr("\nOK\n");
135+ set_graphmode(0);
136+ g_use_graphic=0;
137+
138+ return 0;
139+}
--- mips/tags/zoea1.00/compiler.c (nonexistent)
+++ mips/tags/zoea1.00/compiler.c (revision 148)
@@ -0,0 +1,143 @@
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+void start_program(void* addr, void* memory){
11+ static unsigned int stored_sp;
12+ // Store s0-s7, fp, and ra in stacks
13+ asm volatile("#":::"s0");
14+ asm volatile("#":::"s1");
15+ asm volatile("#":::"s2");
16+ asm volatile("#":::"s3");
17+ asm volatile("#":::"s4");
18+ asm volatile("#":::"s5");
19+ asm volatile("#":::"s6");
20+ asm volatile("#":::"s7");
21+ asm volatile("#":::"fp");
22+ asm volatile("#":::"ra");
23+ // Store sp in stored_sp
24+ asm volatile("la $v0,%0"::"i"(&stored_sp));
25+ asm volatile("sw $sp,0($v0)");
26+ // Shift sp for safety
27+ asm volatile("addiu $sp,$sp,-8");
28+ // Register vector for unexpected NEXT/RETURN
29+ asm volatile("la $v0,%0"::"i"(&err_unexp_next));
30+ asm volatile("sw $v0,4($sp)");
31+ // Store end address in g_end_addr
32+ asm volatile("la $v0,%0"::"i"(&g_end_addr));
33+ asm volatile("la $v1,label");
34+ asm volatile("sw $v1,0($v0)");
35+ // Set s7 for easy calling call_library()
36+ asm volatile("la $s7,%0"::"i"(&call_library));
37+ // Set fp and execute program
38+ asm volatile("addu $fp,$zero,$a1");
39+ asm volatile("jr $a0");
40+ // Restore sp from stored_sp
41+ asm volatile("label:");
42+ asm volatile("la $v0,%0"::"i"(&stored_sp));
43+ asm volatile("lw $sp,0($v0)");
44+ // Restore registers from stack and return
45+ return;
46+}
47+
48+int get_gp(void){
49+ asm volatile("addu $v0,$gp,$zero");
50+}
51+
52+int get_fp(void){
53+ asm volatile("addu $v0,$fp,$zero");
54+}
55+
56+
57+void shift_obj(int* src, int* dst, int len){
58+ int i;
59+ if (dst<src) {
60+ for(i=0;i<len;i++){
61+ dst[i]=src[i];
62+ }
63+ } else if (src<dst) {
64+ for(i=len-1;0<=i;i--){
65+ dst[i]=src[i];
66+ }
67+ }
68+}
69+
70+int strncmp(char* str1, char* str2, int len){
71+ int i;
72+ for (i=0;i<len;i++) {
73+ if (str1[i]>str2[i]) return 1;
74+ if (str1[i]<str2[i]) return -1;
75+ }
76+ return 0;
77+}
78+
79+int nextCodeIs(char* str){
80+ int len;
81+ for(len=0;str[len];len++);
82+ if (!strncmp(g_source+g_srcpos,str,len)) {
83+ if ('A'<=str[len-1] && str[len-1]<='Z') {
84+ // When the last character of str is alphabet,
85+ // the next character in source must be space, enter, or ':'.
86+ if (0x20<g_source[g_srcpos+len] && g_source[g_srcpos+len]!=':') return 0;
87+ }
88+ // String matches in the current position in source.
89+ g_srcpos+=len;
90+ return len;
91+ } else {
92+ // String didn't match.
93+ return 0;
94+ }
95+}
96+
97+char* compile_line(void){
98+ char b1;
99+ char* err;
100+ g_line++;
101+ g_fileline++;
102+ // Check if line number exists
103+ next_position();
104+ b1=g_source[g_srcpos];
105+ if (b1<0x20) {
106+ // The end of line.
107+ // Don't add $s6-setting command.
108+ if (g_source[g_srcpos]==0x0D && g_source[g_srcpos+1]==0x0A) g_srcpos++;
109+ g_srcpos++;
110+ return 0;
111+ } else if ('0'<=b1 && b1<='9') {
112+ // Line number exists
113+ err=get_label();
114+ if (err) return err;
115+ g_line=g_label;
116+ }
117+ // Store line number in $s6
118+ if (!(g_line&0xFFFF0000)) {
119+ // Line number must be less than 65536.
120+ // If not, it is invalid number.
121+ // Check existing line with the same number here.
122+ if (search_label(g_line)) {
123+ // Error: duplicate lines
124+ printstr("Line ");
125+ printstr(resolve_label(g_line));
126+ return ERR_MULTIPLE_LABEL;
127+ }
128+ check_obj_space(1);
129+ g_object[g_objpos++]=0x34160000|g_line; //ori s6,zero,xxxx;
130+ }
131+ while(g_source[g_srcpos]!=0x0D && g_source[g_srcpos]!=0x0A){
132+ err=statement();
133+ if (err) return err;
134+ next_position();
135+ if (g_source[g_srcpos]==':') {
136+ g_srcpos++;
137+ next_position();
138+ }
139+ }
140+ if (g_source[g_srcpos]==0x0D && g_source[g_srcpos+1]==0x0A) g_srcpos++;
141+ g_srcpos++;
142+ return 0;
143+}
\ No newline at end of file
--- mips/tags/zoea1.00/file.c (nonexistent)
+++ mips/tags/zoea1.00/file.c (revision 148)
@@ -0,0 +1,99 @@
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+
12+static FSFILE* g_fhandle;
13+static char* g_fbuff;
14+static int g_size;
15+
16+char* init_file(char* buff,char* appname){
17+ // Open file
18+ g_fhandle=FSfopen(appname,"r");
19+ if (!g_fhandle) {
20+ return ERR_UNKNOWN;
21+ }
22+ g_fbuff=buff;
23+ g_line=0;
24+ g_fileline=0;
25+ return 0;
26+}
27+
28+void close_file(){
29+ FSfclose(g_fhandle);
30+}
31+
32+void read_file(int blocklen){
33+ int i;
34+ static char in_string, escape;
35+ // blocklen is either 512 or 256.
36+ if (blocklen==512) {
37+ // This is first read. Initialize parameter(s).
38+ in_string=0;
39+ escape=0;
40+ } else if (g_size<512) {
41+ // Already reached the end of file.
42+ return;
43+ } else {
44+ // Shift buffer and source position 256 bytes.
45+ for(i=0;i<256;i++) g_fbuff[i]=g_fbuff[i+256];
46+ g_srcpos-=256;
47+ }
48+ // Read 512 or 256 bytes from SD card.
49+ g_size=512-blocklen+FSfread((void*)&g_fbuff[512-blocklen],1,blocklen,g_fhandle);
50+ // Some modifications of text for easy compiling.
51+ for(i=512-blocklen;i<512;i++){
52+ if (in_string) {
53+ if (g_fbuff[i]=='\\' && !escape) {
54+ escape=1;
55+ } else {
56+ escape=0;
57+ if (g_fbuff[i]=='"') in_string=0;
58+ }
59+ } else {
60+ // If not in string, all upper cases.
61+ if (g_fbuff[i]=='"') in_string=1;
62+ else if ('a'<=g_fbuff[i] && g_fbuff[i]<='z') g_fbuff[i]+='A'-'a';
63+ // If not in string, tabs will be spaces.
64+ else if ('\t'==g_fbuff[i]) g_fbuff[i]=' ';
65+ }
66+ if (g_fbuff[i]==0x0a || g_fbuff[i]==0x0d) in_string=escape=0;
67+ }
68+ return;
69+}
70+
71+char* compile_file(){
72+ int i;
73+ char* err;
74+ // Read first 512 bytes
75+ read_file(512);
76+ // Compile line by line
77+ while (g_size==512) {
78+ err=compile_line();
79+ if (err) return err;
80+ // Maintain at least 256 characters in cache.
81+ if (256<=g_srcpos) read_file(256);
82+ }
83+ // Return code at the end
84+ g_source[g_size]=0x0d;
85+ // Compile last few lines.
86+ while(g_srcpos<g_size-1){
87+ err=compile_line();
88+ if (err) return err;
89+ }
90+ // Add "DATA 0" and "END" statements.
91+ g_source="DATA 0:END\n";
92+ g_srcpos=0;
93+ err=compile_line();
94+ if (err) return err;
95+ g_srcpos=-1;
96+ // No error occured
97+ return 0;
98+}
99+
--- mips/tags/zoea1.00/compiler.h (nonexistent)
+++ mips/tags/zoea1.00/compiler.h (revision 148)
@@ -0,0 +1,303 @@
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+/* Definitions */
9+// Number of variables (including temporary ones)
10+#define ALLOC_VAR_NUM 36
11+// Number of blocks that can be assigned for memory allocation (including ALLOC_VAR_NUM)
12+#define ALLOC_BLOCK_NUM 48
13+// Block # dedicated for PCG
14+#define ALLOC_PCG_BLOCK 36
15+// Block # dedicated for GRAPHIC
16+#define ALLOC_GRAPHIC_BLOCK 37
17+// Start # of permanent blocks
18+#define ALLOC_PERM_BLOCK 38
19+
20+// Persistent RAM bytes used for object, heap and exception data
21+#define PERSISTENT_RAM_SIZE (1024*56)
22+// Exception data area bytes
23+#define EXCEPTION_DATA_SIZE (64)
24+// RAM size used for object and heap
25+#define RAMSIZE (PERSISTENT_RAM_SIZE-EXCEPTION_DATA_SIZE)
26+
27+/* Enums */
28+enum variable{
29+ VAR_INTEGER,
30+ VAR_FLOAT,
31+ VAR_STRING
32+};
33+
34+enum operator{
35+ OP_VOID=0,
36+ OP_OR =1,
37+ OP_AND =2,
38+ OP_XOR =3,
39+ OP_EQ =4,
40+ OP_NEQ =5,
41+ OP_LT =6,
42+ OP_LTE =7,
43+ OP_MT =8,
44+ OP_MTE =9,
45+ OP_SHL =10,
46+ OP_SHR =11,
47+ OP_ADD =12,
48+ OP_SUB =13,
49+ OP_MUL =14,
50+ OP_DIV =15,
51+ OP_REM =16
52+};
53+enum libs{
54+ LIB_SOUND,
55+ LIB_MUSICFUNC,
56+ LIB_MUSIC,
57+ LIB_SETDRAWCOUNT,
58+ LIB_DRAWCOUNT,
59+ LIB_PALETTE,
60+ LIB_GPALETTE,
61+ LIB_BGCOLOR,
62+ LIB_CURSOR,
63+ LIB_CLS,
64+ LIB_GCLS,
65+ LIB_COLOR,
66+ LIB_GCOLOR,
67+ LIB_KEYS,
68+ LIB_RESTORE,
69+ LIB_RESTORE2,
70+ LIB_READ,
71+ LIB_MIDSTR,
72+ LIB_CLEAR,
73+ LIB_DIV0,
74+ LIB_LETSTR,
75+ LIB_STRNCMP,
76+ LIB_RND,
77+ LIB_DEC,
78+ LIB_HEX,
79+ LIB_CHR,
80+ LIB_CONNECT_STRING,
81+ LIB_STRING,
82+ LIB_PRINTSTR,
83+ LIB_LABEL,
84+ LIB_DIM,
85+ LIB_VAL,
86+ LIB_INPUT,
87+ LIB_INKEY,
88+ LIB_USEPCG,
89+ LIB_PCG,
90+ LIB_SCROLL,
91+ LIB_WAIT,
92+ LIB_VAR_PUSH,
93+ LIB_VAR_POP,
94+ LIB_SYSTEM,
95+ LIB_SPRINTF,
96+ LIB_FLOAT,
97+ LIB_FLOATFUNCS,
98+ LIB_CREAD,
99+ LIB_USEGRAPHIC,
100+ LIB_GRAPHIC,
101+ LIB_DEBUG
102+};
103+enum functions{
104+ FUNC_FLOAT,
105+ FUNC_INT,
106+ FUNC_VALSHARP,
107+ FUNC_SIN,
108+ FUNC_COS,
109+ FUNC_TAN,
110+ FUNC_ASIN,
111+ FUNC_ACOS,
112+ FUNC_ATAN,
113+ FUNC_SINH,
114+ FUNC_COSH,
115+ FUNC_TANH,
116+ FUNC_EXP,
117+ FUNC_LOG,
118+ FUNC_LOG10,
119+ FUNC_POW,
120+ FUNC_SQRT,
121+ FUNC_CEIL,
122+ FUNC_FLOOR,
123+ FUNC_FABS,
124+ FUNC_MODF,
125+ FUNC_FMOD,
126+ FUNC_PSET,
127+ FUNC_LINE,
128+ FUNC_BOXFILL,
129+ FUNC_CIRCLE,
130+ FUNC_CIRCLEFILL,
131+ FUNC_GPRINT,
132+ FUNC_PUTBMP,
133+ FUNC_PUTBMP2,
134+ FUNC_GCOLOR,
135+ FUNC_POINT,
136+};
137+
138+/* Global vars (see globalvers.c) */
139+extern int g_intconst;
140+extern char g_valueisconst;
141+extern int g_rnd_seed;
142+extern unsigned int g_label;
143+extern int g_sdepth;
144+extern int g_maxsdepth;
145+extern enum variable g_lastvar;
146+extern char* g_source;
147+extern int g_srcpos;
148+extern int g_line;
149+extern int g_fileline;
150+extern int* g_object;
151+extern int g_objpos;
152+extern int* g_objmax;
153+extern const char* g_err_str[];
154+extern const unsigned char g_priority[];
155+extern enum operator g_last_op;
156+extern int g_end_addr;
157+extern int g_gp;
158+extern int g_s6;
159+extern char RAM[RAMSIZE];
160+extern unsigned int g_ex_data[EXCEPTION_DATA_SIZE/4];
161+extern int g_var_mem[ALLOC_BLOCK_NUM];
162+extern unsigned short g_var_pointer[ALLOC_BLOCK_NUM];
163+extern unsigned short g_var_size[ALLOC_BLOCK_NUM];
164+extern char g_temp_area_used;
165+extern int* g_heap_mem;
166+extern int g_max_mem;
167+extern char g_disable_break;
168+extern unsigned char* g_pcg_font;
169+extern char g_use_graphic;
170+extern unsigned short* g_graphic_area;
171+
172+/* Prototypes */
173+int get_gp(void);
174+int get_fp(void);
175+void start_program(void* addr, void* memory);
176+void shift_obj(int* src, int* dst, int len);
177+char* compile_line(void);
178+int nextCodeIs(char* str);
179+
180+char* init_file(char* buff,char* appname);
181+void close_file();
182+void read_file(int blocklen);
183+char* compile_file();
184+
185+void err_break(void);
186+void err_music(char* str);
187+void err_data_not_found(void);
188+void err_str_complex(void);
189+void err_label_not_found(void);
190+void err_no_mem(void);
191+void err_div_zero(void);
192+void err_unkonwn(void);
193+void err_unexp_next(void);
194+void err_no_block(void);
195+char* resolve_label(int s6);
196+
197+void set_sound(unsigned long* data);
198+int musicRemaining(void);
199+void set_music(char* str);
200+void init_music(void);
201+
202+char* statement(void);
203+char* gosub_statement();
204+char* graphic_statement(enum functions func);
205+
206+char* function(void);
207+char* str_function(void);
208+char* float_function(void);
209+
210+void call_library(void);
211+void reset_dataread();
212+
213+void free_temp_str(char* str);
214+void* alloc_memory(int size, int var_num);
215+void* calloc_memory(int size, int var_num);
216+void move_to_perm_block(int var_num);
217+void move_from_perm_block(int var_num);
218+
219+char* link(void);
220+char* get_label(void);
221+void* search_label(unsigned int label);
222+
223+char* get_string();
224+char* simple_string(void);
225+
226+char* get_operator(void);
227+char* get_floatOperator(void);
228+char* calculation(enum operator op);
229+char* calculation_float(enum operator op);
230+int lib_float(int ia0,int iv0, enum operator a1);
231+
232+char* get_dim_value(char b1);
233+char* get_simple_value(void);
234+char* get_value();
235+char* get_floatOrValue();
236+char* get_stringFloatOrValue();
237+
238+void blue_screen(void);
239+
240+char* get_float();
241+
242+/* Error messages */
243+#define ERR_SYNTAX (char*)(g_err_str[0])
244+#define ERR_NE_BINARY (char*)(g_err_str[1])
245+#define ERR_NE_MEMORY (char*)(g_err_str[2])
246+#define ERR_DIV_0 (char*)(g_err_str[3])
247+#define ERR_NY_I (char*)(g_err_str[4])
248+#define ERR_LABEL_NF (char*)(g_err_str[5])
249+#define ERR_LABEL_LONG (char*)(g_err_str[6])
250+#define ERR_STR_COMPLEX (char*)(g_err_str[7])
251+#define ERR_DATA_NF (char*)(g_err_str[8])
252+#define ERR_UNKNOWN (char*)(g_err_str[9])
253+#define ERR_MUSIC (char*)(g_err_str[10])
254+#define ERR_MULTIPLE_LABEL (char*)(g_err_str[11])
255+#define ERR_BREAK (char*)(g_err_str[12])
256+#define ERR_UNEXP_NEXT (char*)(g_err_str[13])
257+#define ERR_NO_BLOCK (char*)(g_err_str[14])
258+#define ERR_GOSUB_ASH (char*)(g_err_str[15])
259+#define ERR_INVALID_BREAK (char*)(g_err_str[16])
260+#define ERR_INVALID_ELSEIF (char*)(g_err_str[17])
261+
262+/* Macros */
263+
264+// Skip blanc(s) in source code
265+#define next_position() while(g_source[g_srcpos]==' ') {g_srcpos++;}
266+
267+// Check if object area is not full.
268+#define check_obj_space(x) if (g_objmax<g_object+g_objpos+(x)) return ERR_NE_BINARY
269+
270+// Returns priority of operator
271+#define priority(x) (int)g_priority[(int)(x)]
272+
273+// Insert code for calling library
274+//02E0F809 jalr ra,s7
275+//24070000 addiu a3,zero,0000
276+#define call_lib_code(x) \
277+ check_obj_space(2);\
278+ g_object[g_objpos++]=0x02E0F809;\
279+ g_object[g_objpos++]=0x24070000|((x)&0x0000FFFF)
280+
281+// Division macro for unsigned long
282+// Valid for 31 bits for all cases and 32 bits for some cases
283+#define div32(x,y,z) ((((unsigned long long)((unsigned long)(x)))*((unsigned long long)((unsigned long)(y))))>>(z))
284+
285+// Divide by 10 (valid for 32 bits)
286+#define div10_32(x) div32(x,0xcccccccd,35)
287+#define rem10_32(x) ((x)-10*div10_32(x))
288+
289+// Divide by 36 (valid for 32 bits)
290+#define div36_32(x) div32(x,0xe38e38e4,37)
291+#define rem36_32(x) (x-36*div36_32(x))
292+
293+// Check break key or buttons when executing BASIC code.
294+// In PS/2 mode, detect ctrl-break.
295+// In button mode, detect pushing four buttons are pushed simultaneously.
296+#define check_break() \
297+ if (g_disable_break==0) {\
298+ if (inPS2MODE()) {\
299+ if (ps2keystatus[0x03]) err_break();\
300+ } else {\
301+ if ((PORTB&0x4c80)==0) err_break();\
302+ }\
303+ }
--- mips/tags/zoea1.00/function.c (nonexistent)
+++ mips/tags/zoea1.00/function.c (revision 148)
@@ -0,0 +1,517 @@
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+ call_lib_code(LIB_MUSICFUNC);
13+ return 0;
14+}
15+
16+char* read_function(){
17+ call_lib_code(LIB_READ);
18+ return 0;
19+}
20+
21+char* cread_function(){
22+ call_lib_code(LIB_CREAD);
23+ return 0;
24+}
25+
26+char* gosub_function(){
27+ // Check if garbage collection has been done.
28+ // This check is required because the used temporary area would be changed
29+ // in sub routine.
30+ if (g_temp_area_used) return ERR_GOSUB_ASH;
31+ return gosub_statement();
32+}
33+char* strncmp_function(){
34+ char* err;
35+ err=get_string();
36+ if (err) return err;
37+ check_obj_space(2);
38+ g_object[g_objpos++]=0x27BDFFF8; // addiu sp,sp,-8
39+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
40+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
41+ g_srcpos++;
42+ err=get_string();
43+ if (err) return err;
44+ check_obj_space(1);
45+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
46+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
47+ g_srcpos++;
48+ err=get_value();
49+ if (err) return err;
50+ check_obj_space(3);
51+ g_object[g_objpos++]=0x8FA40008; // lw a0,8(sp)
52+ g_object[g_objpos++]=0x8FA50004; // lw a1,4(sp)
53+ g_object[g_objpos++]=0x27BD0008; // addiu sp,sp,8
54+ call_lib_code(LIB_STRNCMP);
55+ return 0;
56+}
57+char* len_function(){
58+ char* err;
59+ err=get_string();
60+ if (err) return err;
61+ check_obj_space(5);
62+ g_object[g_objpos++]=0x2443FFFF; // addiu v1,v0,-1
63+ // loop:
64+ g_object[g_objpos++]=0x80640001; // lb a0,1(v1)
65+ g_object[g_objpos++]=0x1480FFFE; // bne a0,zero,loop
66+ g_object[g_objpos++]=0x24630001; // addiu v1,v1,1
67+ g_object[g_objpos++]=0x00621023; // subu v0,v1,v0
68+ return 0;
69+}
70+
71+char* asc_function(){
72+ char* err;
73+ err=get_string();
74+ if (err) return err;
75+ check_obj_space(1);
76+ g_object[g_objpos++]=0x90420000; // lbu v0,0(v0)
77+ return 0;
78+}
79+
80+char* val_function(){
81+ char* err;
82+ err=get_string();
83+ if (err) return err;
84+ call_lib_code(LIB_VAL);
85+ return 0;
86+}
87+
88+char* peek_function(){
89+ char* err;
90+ err=get_value();
91+ if (err) return err;
92+ check_obj_space(1);
93+ g_object[g_objpos++]=0x90420000; // lbu v0,0(v0)
94+ return 0;
95+}
96+
97+char* sgn_function(){
98+ char* err;
99+ err=get_value();
100+ if (err) return err;
101+ check_obj_space(5);
102+ g_object[g_objpos++]=0x10400004; // beq v0,zero,end
103+ g_object[g_objpos++]=0x24030001; // addiu v1,zero,1
104+ g_object[g_objpos++]=0x1C400002; // bgtz v0,end
105+ g_object[g_objpos++]=0x00601021; // addu v0,v1,zero
106+ g_object[g_objpos++]=0x00031023; // subu v0,zero,v1
107+ // end:
108+ return 0;
109+}
110+
111+char* abs_function(){
112+ char* err;
113+ err=get_value();
114+ if (err) return err;
115+ check_obj_space(3);
116+ g_object[g_objpos++]=0x00021FC3; //sra v1,v0,0x1f
117+ g_object[g_objpos++]=0x00621026; //xor v0,v1,v0
118+ g_object[g_objpos++]=0x00431023; //subu v0,v0,v1
119+ return 0;
120+}
121+
122+char* not_function(){
123+ char* err;
124+ err=get_value();
125+ if (err) return err;
126+ check_obj_space(1);
127+ g_object[g_objpos++]=0x2C420001; //sltiu v0,v0,1
128+ return 0;
129+}
130+
131+char* rnd_function(){
132+ call_lib_code(LIB_RND);
133+ return 0;
134+}
135+
136+
137+char* chr_function(void){
138+ char* err;
139+ err=get_value();
140+ if (err) return err;
141+ call_lib_code(LIB_CHR);
142+ return 0;
143+}
144+char* hex_function(void){
145+ char* err;
146+ err=get_value();
147+ if (err) return err;
148+ if (g_source[g_srcpos]==',') {
149+ // Second argument found.
150+ // Get is as $a0.
151+ g_srcpos++;
152+ check_obj_space(2);
153+ g_object[g_objpos++]=0x27BDFFFC; //addiu sp,sp,-4
154+ g_object[g_objpos++]=0xAFA20004; //sw v0,4(sp)
155+ err=get_value();
156+ if (err) return err;
157+ check_obj_space(3);
158+ g_object[g_objpos++]=0x00022021; //a0,zero,v0
159+ g_object[g_objpos++]=0x8FA20004; //lw v0,4(sp)
160+ g_object[g_objpos++]=0x27BD0004; //addiu sp,sp,4
161+ } else {
162+ // Second argument not found.
163+ // Set $a0 to 0.
164+ check_obj_space(1);
165+ g_object[g_objpos++]=0x24040000; //addiu a0,zero,0
166+ }
167+ call_lib_code(LIB_HEX);
168+ return 0;
169+}
170+
171+char* dec_function(void){
172+ char* err;
173+ err=get_value();
174+ if (err) return err;
175+ call_lib_code(LIB_DEC);
176+ return 0;
177+}
178+
179+char* keys_function(void){
180+ char* err;
181+ next_position();
182+ if (g_source[g_srcpos]==')') {
183+ check_obj_space(1);
184+ g_object[g_objpos++]=0x3402003F; //ori v0,zero,0x3f
185+ } else {
186+ err=get_value();
187+ if (err) return err;
188+ }
189+ call_lib_code(LIB_KEYS);
190+ return 0;
191+}
192+
193+char* tvram_function(void){
194+ char* err;
195+ int i;
196+ next_position();
197+ if (g_source[g_srcpos]==')') {
198+ i=(int)(&TVRAM[0]);
199+ i-=g_gp;
200+ check_obj_space(1);
201+ g_object[g_objpos++]=0x27820000|(i&0x0000FFFF); // addiu v0,gp,xxxx
202+ } else {
203+ err=get_value();
204+ if (err) return err;
205+ i=(int)(&TVRAM[0]);
206+ i-=g_gp;
207+ check_obj_space(3);
208+ g_object[g_objpos++]=0x27830000|(i&0x0000FFFF); // addiu v1,gp,xxxx
209+ g_object[g_objpos++]=0x00621821; // addu v1,v1,v0
210+ g_object[g_objpos++]=0x90620000; // lbu v0,0(v1)
211+ }
212+ return 0;
213+}
214+
215+char* drawcount_function(void){
216+ call_lib_code(LIB_DRAWCOUNT);
217+ return 0;
218+}
219+
220+char* input_function(void){
221+ call_lib_code(LIB_INPUT);
222+ return 0;
223+}
224+
225+char* inkey_function(void){
226+ char* err;
227+ next_position();
228+ if (g_source[g_srcpos]==')') {
229+ check_obj_space(1);
230+ g_object[g_objpos++]=0x34020000; //ori v0,zero,0x00
231+ } else {
232+ err=get_value();
233+ if (err) return err;
234+ }
235+ call_lib_code(LIB_INKEY);
236+ return 0;
237+}
238+
239+char* args_function(void){
240+ char* err;
241+ int i;
242+ err=get_value();
243+ if (err) return err;
244+ i=g_object[g_objpos-1];
245+ if ((i>>16)==0x3402) {
246+ // Previous object is "ori v0,zero,xxxx".
247+ i&=0xffff;
248+ i=(i+1)<<2;
249+ g_object[g_objpos-1]=0x8EA20000|i; // lw v0,xx(s5)
250+ } else {
251+ check_obj_space(3);
252+ g_object[g_objpos++]=0x00021080; // sll v0,v0,0x2
253+ g_object[g_objpos++]=0x02A21021; // addu v0,s5,v0
254+ g_object[g_objpos++]=0x8C420004; // lw v0,4(v0)
255+ }
256+ return 0;
257+}
258+
259+char* system_function(void){
260+ char* err;
261+ err=get_value();
262+ if (err) return err;
263+ g_object[g_objpos++]=0x00402021; // addu a0,v0,zero
264+ call_lib_code(LIB_SYSTEM);
265+ return 0;
266+}
267+
268+char* sprintf_function(void){
269+ char* err;
270+ err=get_string();
271+ if (err) return err;
272+ next_position();
273+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
274+ g_srcpos++;
275+ check_obj_space(2);
276+ g_object[g_objpos++]=0x27BDFFFC; //addiu sp,sp,-4
277+ g_object[g_objpos++]=0xAFA20004; //sw v0,4(sp)
278+ err=get_float();
279+ if (err) return err;
280+ check_obj_space(3);
281+ g_object[g_objpos++]=0x00022021; //addu a0,zero,v0
282+ g_object[g_objpos++]=0x8FA20004; //lw v0,4(sp)
283+ g_object[g_objpos++]=0x27BD0004; //addiu sp,sp,4
284+ call_lib_code(LIB_SPRINTF);
285+ return 0;
286+}
287+
288+char* floatstr_function(void){
289+ char* err;
290+ err=get_float();
291+ if (err) return err;
292+ check_obj_space(2);
293+ g_object[g_objpos++]=0x00022021; //addu a0,zero,v0
294+ g_object[g_objpos++]=0x34020000; //ori v0,zero,0x0000
295+ call_lib_code(LIB_SPRINTF);
296+ return 0;
297+}
298+
299+char* floatsharp_function(void){
300+ char* err;
301+ err=get_value();
302+ if (err) return err;
303+ check_obj_space(1);
304+ g_object[g_objpos++]=0x34050000|(FUNC_FLOAT&0x0000ffff);// ori a1,zero,xxxx
305+ call_lib_code(LIB_FLOATFUNCS);
306+ return 0;
307+}
308+
309+char* valsharp_function(void){
310+ char* err;
311+ err=get_string();
312+ if (err) return err;
313+ check_obj_space(1);
314+ g_object[g_objpos++]=0x34050000|(FUNC_VALSHARP&0x0000ffff);// ori a1,zero,xxxx
315+ call_lib_code(LIB_FLOATFUNCS);
316+ return 0;
317+}
318+
319+char* int_function(void){
320+ char* err;
321+ err=get_float();
322+ if (err) return err;
323+ check_obj_space(1);
324+ g_object[g_objpos++]=0x34050000|(FUNC_INT&0x0000ffff);// ori a1,zero,xxxx
325+ call_lib_code(LIB_FLOATFUNCS);
326+ return 0;
327+}
328+
329+char* float_constant(float val){
330+ volatile int i;
331+ ((float*)(&i))[0]=val;
332+ if (i&0xFFFF0000) {
333+ // 32 bit
334+ check_obj_space(2);
335+ g_object[g_objpos++]=0x3C020000|((i>>16)&0x0000FFFF); // lui v0,xxxx
336+ g_object[g_objpos++]=0x34420000|(i&0x0000FFFF); // ori v0,v0,xxxx
337+ } else {
338+ // 16 bit
339+ check_obj_space(1);
340+ g_object[g_objpos++]=0x34020000|(i&0x0000FFFF); // ori v0,zero,xxxx
341+ }
342+ return 0;
343+}
344+
345+char* float_1param_function(enum functions func){
346+ char* err;
347+ err=get_float();
348+ if (err) return err;
349+ check_obj_space(1);
350+ g_object[g_objpos++]=0x34050000|(func&0x0000ffff);// ori a1,zero,xxxx
351+ call_lib_code(LIB_FLOATFUNCS);
352+ return 0;
353+}
354+
355+char* float_2param_function(enum functions func){
356+ char* err;
357+ err=get_float();
358+ if (err) return err;
359+ next_position();
360+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
361+ g_srcpos++;
362+ check_obj_space(2);
363+ g_object[g_objpos++]=0x27BDFFFC; //addiu sp,sp,-4
364+ g_object[g_objpos++]=0xAFA20004; //sw v0,4(sp)
365+ err=get_float();
366+ if (err) return err;
367+ check_obj_space(4);
368+ g_object[g_objpos++]=0x00022021; //addu a0,zero,v0
369+ g_object[g_objpos++]=0x8FA20004; //lw v0,4(sp)
370+ g_object[g_objpos++]=0x27BD0004; //addiu sp,sp,4
371+ g_object[g_objpos++]=0x34050000|(func&0x0000ffff);// ori a1,zero,xxxx
372+ call_lib_code(LIB_FLOATFUNCS);
373+ return 0;
374+}
375+
376+char* float_function(void){
377+ char* err;
378+ if (nextCodeIs("FLOAT#(")) {
379+ err=floatsharp_function();
380+ } else if (nextCodeIs("VAL#(")) {
381+ err=valsharp_function();
382+ } else if (nextCodeIs("SIN#(")) {
383+ err=float_1param_function(FUNC_SIN);
384+ } else if (nextCodeIs("COS#(")) {
385+ err=float_1param_function(FUNC_COS);
386+ } else if (nextCodeIs("TAN#(")) {
387+ err=float_1param_function(FUNC_TAN);
388+ } else if (nextCodeIs("ASIN#(")) {
389+ err=float_1param_function(FUNC_ASIN);
390+ } else if (nextCodeIs("ACOS#(")) {
391+ err=float_1param_function(FUNC_ACOS);
392+ } else if (nextCodeIs("ATAN#(")) {
393+ err=float_1param_function(FUNC_ATAN);
394+ } else if (nextCodeIs("SINH#(")) {
395+ err=float_1param_function(FUNC_SINH);
396+ } else if (nextCodeIs("COSH#(")) {
397+ err=float_1param_function(FUNC_COSH);
398+ } else if (nextCodeIs("TANH#(")) {
399+ err=float_1param_function(FUNC_TANH);
400+ } else if (nextCodeIs("EXP#(")) {
401+ err=float_1param_function(FUNC_EXP);
402+ } else if (nextCodeIs("LOG#(")) {
403+ err=float_1param_function(FUNC_LOG);
404+ } else if (nextCodeIs("LOG10#(")) {
405+ err=float_1param_function(FUNC_LOG10);
406+ } else if (nextCodeIs("POW#(")) {
407+ err=float_2param_function(FUNC_POW);
408+ } else if (nextCodeIs("SQRT#(")) {
409+ err=float_1param_function(FUNC_SQRT);
410+ } else if (nextCodeIs("CEIL#(")) {
411+ err=float_1param_function(FUNC_CEIL);
412+ } else if (nextCodeIs("FLOOR#(")) {
413+ err=float_1param_function(FUNC_FLOOR);
414+ } else if (nextCodeIs("FABS#(")) {
415+ err=float_1param_function(FUNC_FABS);
416+ } else if (nextCodeIs("MODF#(")) {
417+ err=float_1param_function(FUNC_MODF);
418+ } else if (nextCodeIs("FMOD#(")) {
419+ err=float_2param_function(FUNC_FMOD);
420+ } else if (nextCodeIs("GOSUB#(")) {
421+ err=gosub_function();
422+ } else if (nextCodeIs("ARGS#(")) {
423+ err=args_function();
424+ } else if (nextCodeIs("PI#")) {
425+ return float_constant(3.141593);
426+ } else {
427+ return ERR_SYNTAX;
428+ }
429+ if (err) return err;
430+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
431+ g_srcpos++;
432+ return 0;
433+}
434+
435+char* str_function(void){
436+ char* err;
437+ if (nextCodeIs("CHR$(")) {
438+ err=chr_function();
439+ } else if (nextCodeIs("HEX$(")) {
440+ err=hex_function();
441+ } else if (nextCodeIs("DEC$(")) {
442+ err=dec_function();
443+ } else if (nextCodeIs("INPUT$(")) {
444+ err=input_function();
445+ } else if (nextCodeIs("GOSUB$(")) {
446+ err=gosub_function();
447+ } else if (nextCodeIs("ARGS$(")) {
448+ err=args_function();
449+ } else if (nextCodeIs("READ$(")) {
450+ err=read_function();
451+ } else if (nextCodeIs("SPRINTF$(")) {
452+ err=sprintf_function();
453+ } else if (nextCodeIs("FLOAT$(")) {
454+ err=floatstr_function();
455+ } else if (nextCodeIs("SYSTEM$(")) {
456+ err=system_function();
457+ } else {
458+ return ERR_SYNTAX;
459+ }
460+ if (err) return err;
461+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
462+ g_srcpos++;
463+ return 0;
464+}
465+
466+char* function(void){
467+ char* err;
468+ if (nextCodeIs("NOT(")) {
469+ err=not_function();
470+ } else if (nextCodeIs("DRAWCOUNT(")) {
471+ err=drawcount_function();
472+ } else if (nextCodeIs("MUSIC(")) {
473+ err=music_function();
474+ } else if (nextCodeIs("TVRAM(")) {
475+ err=tvram_function();
476+ } else if (nextCodeIs("KEYS(")) {
477+ err=keys_function();
478+ } else if (nextCodeIs("READ(")) {
479+ err=read_function();
480+ } else if (nextCodeIs("CREAD(")) {
481+ err=cread_function();
482+ } else if (nextCodeIs("GOSUB(")) {
483+ err=gosub_function();
484+ } else if (nextCodeIs("STRNCMP(")) {
485+ err=strncmp_function();
486+ } else if (nextCodeIs("PEEK(")) {
487+ err=peek_function();
488+ } else if (nextCodeIs("LEN(")) {
489+ err=len_function();
490+ } else if (nextCodeIs("ASC(")) {
491+ err=asc_function();
492+ } else if (nextCodeIs("SGN(")) {
493+ err=sgn_function();
494+ } else if (nextCodeIs("ABS(")) {
495+ err=abs_function();
496+ } else if (nextCodeIs("RND(")) {
497+ err=rnd_function();
498+ } else if (nextCodeIs("VAL(")) {
499+ err=val_function();
500+ } else if (nextCodeIs("INKEY(")) {
501+ err=inkey_function();
502+ } else if (nextCodeIs("ARGS(")) {
503+ err=args_function();
504+ } else if (nextCodeIs("SYSTEM(")) {
505+ err=system_function();
506+ } else if (nextCodeIs("INT(")) {
507+ err=int_function();
508+ } else if (nextCodeIs("GCOLOR(")) {
509+ err=graphic_statement(FUNC_GCOLOR);
510+ } else {
511+ return ERR_SYNTAX;
512+ }
513+ if (err) return err;
514+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
515+ g_srcpos++;
516+ return err;
517+}
--- mips/tags/zoea1.00/string.c (nonexistent)
+++ mips/tags/zoea1.00/string.c (revision 148)
@@ -0,0 +1,213 @@
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+ Public functions:
10+ char* get_string(void);
11+ char* simple_string(void);
12+*/
13+
14+#include "api.h"
15+#include "compiler.h"
16+
17+char* simple_string(void){
18+ char* err;
19+ unsigned char b1,b2;
20+ int i,j;
21+ next_position();
22+ b1=g_source[g_srcpos];
23+ b2=g_source[g_srcpos+1];
24+ if (b1=='"') {
25+ // Constant string
26+ // Count character number (+1 for \0)
27+ // This may be more than actual character number due to escape sequence.
28+ i=0;
29+ while(1){
30+ i++;
31+ b1=g_source[g_srcpos+i];
32+ if (b1=='"') {
33+ break;
34+ } else if (b1=='\\') {
35+ i++;
36+ } else if (b1<0x20) {
37+ // This is an error, that will be detected later again.
38+ break;
39+ }
40+ };
41+ g_srcpos++;
42+ // Determine required word number
43+ i=(i+3)/4;
44+ // Determine address containing the string
45+ j=(int)(&(g_object[g_objpos+3]));
46+ // Note that using "bgezal zero," must be used to skip some region.
47+ // This is to find embed string in the code.
48+ check_obj_space(2+i);
49+ g_object[g_objpos++]=0x04110000|((i+1)&0x0000FFFF); // bgezal zero,xxxx
50+ g_object[g_objpos++]=0x03E01021; // addu v0,ra,zero
51+ for(j=0;(b1=g_source[g_srcpos++])!='"';j++) {
52+ if (b1=='\\') {
53+ b1=g_source[g_srcpos++];
54+ if (b1=='x' || b1=='X') {
55+ // Hexadecimal
56+ b1=g_source[g_srcpos++];
57+ if ('0'<=b1 && b1<='9') b1=b1-'0';
58+ else if ('A'<=b1 && b1<='F') b1=b1-'A'+10;
59+ else if ('a'<=b1 && b1<='f') b1=b1-'a'+10;
60+ else return ERR_SYNTAX;
61+ b2=g_source[g_srcpos++];
62+ if ('0'<=b2 && b2<='9') b2=b2-'0';
63+ else if ('A'<=b2 && b2<='F') b2=b2-'A'+10;
64+ else if ('a'<=b2 && b2<='f') b2=b2-'a'+10;
65+ else return ERR_SYNTAX;
66+ b1=(b1<<4)|b2;
67+ } else if (b1<0x20) {
68+ return ERR_SYNTAX;
69+ } else {
70+ // \\ or \"
71+ }
72+ } else if (b1<0x20) {
73+ return ERR_SYNTAX;
74+ }
75+ ((char*)(&g_object[g_objpos]))[j]=b1;
76+ }
77+ ((char*)(&g_object[g_objpos]))[j]=0x00;
78+ g_objpos+=i;
79+ } else if ('A'<=b1 && b1<='Z' && b2=='$') {
80+ // String variable
81+ g_srcpos+=2;
82+ next_position();
83+ if (g_source[g_srcpos]=='(') {
84+ // A part of string
85+ g_srcpos++;
86+ err=get_value();
87+ if (err) return err;
88+ if (g_source[g_srcpos]==')') {
89+ g_srcpos++;
90+ // Put -1 to $a0
91+ check_obj_space(1);
92+ g_object[g_objpos++]=0x2404FFFF; // addiu a0,zero,-1
93+ } else if (g_source[g_srcpos]==',') {
94+ g_srcpos++;
95+ // Store $v0 in stack
96+ g_sdepth+=4;
97+ if (g_maxsdepth<g_sdepth) g_maxsdepth=g_sdepth;
98+ check_obj_space(1);
99+ g_object[g_objpos++]=0xAFA20000|g_sdepth; // sw v0,xx(sp)
100+ // Get next value
101+ err=get_value();
102+ if (err) return err;
103+ // Copy $v0 to $a0 and get value from stack to $a0.
104+ check_obj_space(2);
105+ g_object[g_objpos++]=0x00402021; // addu a0,v0,zero
106+ g_object[g_objpos++]=0x8FA20000|g_sdepth; // lw v0,xx(sp)
107+ g_sdepth-=4;
108+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
109+ g_srcpos++;
110+ // Temp area will be used when executing.
111+ g_temp_area_used=1;
112+ } else {
113+ return ERR_SYNTAX;
114+ }
115+ // $a1 is var number, $v0 is position, $a0 is length
116+ check_obj_space(1);
117+ g_object[g_objpos++]=0x24050000|(b1-'A'); // addiu a1,zero,xx
118+ call_lib_code(LIB_MIDSTR);
119+ } else {
120+ // Simple string
121+ check_obj_space(1);
122+ g_object[g_objpos++]=0x8FC20000|((b1-'A')*4); // lw v0,xx(s8)
123+ // String is pointed by $v0
124+ }
125+ } else if ('A'<=b1 && b1<='Z') {
126+ // Function
127+ // String would be pointed by $v0
128+ // Otherwise, it will be assinged in xxx_function() function.
129+ err=str_function();
130+ if (err) return err;
131+ // Temp area would be used when executing.
132+ g_temp_area_used=1;
133+ return 0;
134+ } else {
135+ return ERR_SYNTAX;
136+ }
137+ return 0;
138+}
139+
140+char* get_string_sub(){
141+ char* err;
142+ char b1;
143+ // Obtain initial string
144+ err=simple_string();
145+ if (err) return err;
146+ // Check if connection operator exists
147+ next_position();
148+ b1=g_source[g_srcpos];
149+ if (b1!='+' && b1!='&') return 0; // Exit if connection operator does not exist.
150+ g_srcpos++;
151+ // Connection required.
152+ // Prepare one level of stack for handling
153+ g_sdepth+=4;
154+ if (g_maxsdepth<g_sdepth) g_maxsdepth=g_sdepth;
155+ while(1) {
156+ // Store current pointer in stack
157+ check_obj_space(1);
158+ g_object[g_objpos++]=0xAFA20000|g_sdepth; // sw v0,xx(sp)
159+ // Obtain next string (pointer will be in $v0)
160+ err=simple_string();
161+ if (err) return err;
162+ // Restore previous pointer from stack in $a0 and copy $v0 to $a1
163+ // Call library
164+ check_obj_space(2);
165+ g_object[g_objpos++]=0x8FA40000|g_sdepth; // lw a0,xx(sp)
166+ call_lib_code(LIB_CONNECT_STRING);
167+ // Temp area will be used when executing.
168+ g_temp_area_used=1;
169+ // Check if further connection operator exists
170+ next_position();
171+ b1=g_source[g_srcpos];
172+ if (b1!='+' && b1!='&') break;
173+ g_srcpos++;
174+ }
175+ g_sdepth-=4;
176+ return 0;
177+}
178+
179+char* get_string(){
180+ // This is only the public function.
181+ // Note that this can be called recursively.
182+ // String may contain a function with a parameter of value
183+ // that is a function with a parameter of string.
184+ // Result will be in $v0 as a pointer.
185+ char* err;
186+ char b1;
187+ int i,prevpos;
188+ if (g_sdepth==0) {
189+ // Initialize stack handler
190+ g_maxsdepth=0;
191+ prevpos=g_objpos;
192+ // Stack decrement command will be filled later
193+ check_obj_space(1);
194+ g_objpos++;
195+ }
196+ err=get_string_sub();
197+ if (err) return err;
198+ if (g_sdepth==0) {
199+ if (g_maxsdepth==0) {
200+ // Stack was not used.
201+ shift_obj(&g_object[prevpos+1],&g_object[prevpos],g_objpos-prevpos-1);
202+ g_objpos--;
203+ } else {
204+ // Stack was used.
205+ check_obj_space(1);
206+ g_object[prevpos]=0x27BD0000 | (0-g_maxsdepth) & 0x0000FFFF; // addiu sp,sp,-xx
207+ g_object[g_objpos++]=0x27BD0000 | g_maxsdepth & 0x0000FFFF; // addiu sp,sp,xx
208+ }
209+ }
210+ g_lastvar=VAR_STRING;
211+ return 0;
212+}
213+
--- mips/tags/zoea1.00/statement.c (nonexistent)
+++ mips/tags/zoea1.00/statement.c (revision 148)
@@ -0,0 +1,1387 @@
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+ call_lib_code(LIB_SOUND);
41+ return 0;
42+}
43+char* music_statement(){
44+ char *err;
45+ err=get_string();
46+ call_lib_code(LIB_MUSIC);
47+ return 0;
48+}
49+
50+char* exec_statement(){
51+ char *err;
52+ char b1;
53+ int i,prevpos;
54+ b1=g_source[g_srcpos];
55+ while('0'<=b1 && b1<='9' || b1=='-' || b1=='$'){
56+ prevpos=g_objpos;
57+ g_valueisconst=1;
58+ err=get_simple_value();
59+ if (!g_valueisconst) err=ERR_SYNTAX;
60+ if (err) return err;
61+ check_obj_space(1);
62+ g_objpos=prevpos;
63+ g_object[g_objpos++]=g_intconst;
64+ next_position();
65+ b1=g_source[g_srcpos];
66+ if (b1!=',') break;
67+ g_srcpos++;
68+ next_position();
69+ b1=g_source[g_srcpos];
70+ if (b1==0x0d || b1==0x0a) {
71+ // Multiline DATA/EXEC statement
72+ g_line++;
73+ g_fileline++;
74+ if (b1==0x0D && g_source[g_srcpos+1]==0x0A) g_srcpos++;
75+ g_srcpos++;
76+ // Maintain at least 256 characters in cache.
77+ if (256<=g_srcpos) read_file(256);
78+ next_position();
79+ b1=g_source[g_srcpos];
80+ }
81+ }
82+ return 0;
83+}
84+
85+char* cdata_statement(){
86+ // 0x00000020, 0x00000021, 0x00000022, and 0x00000023 (add/addu/sub/subu zero,zero,zero)
87+ // are the sign of data region
88+ int beginpos,prevpos;
89+ char* err;
90+ char b1;
91+ char* cpy;
92+ int shift=0;
93+ int i=0;
94+ beginpos=g_objpos;
95+ check_obj_space(2);
96+ g_object[g_objpos++]=0x04110000; // bgezal zero,xxxx
97+ g_object[g_objpos++]=0x00000020; // add zero,zero,zero
98+ next_position();
99+ b1=g_source[g_srcpos];
100+ while('0'<=b1 && b1<='9' || b1=='-' || b1=='$'){
101+ prevpos=g_objpos;
102+ g_valueisconst=1;
103+ err=get_simple_value();
104+ if (!g_valueisconst) err=ERR_SYNTAX;
105+ if (g_intconst<0x00 || 0xff<g_intconst) err=ERR_SYNTAX;
106+ if (err) return err;
107+ g_objpos=prevpos;
108+ i|=g_intconst<<shift;
109+ shift+=8;
110+ if (32<=shift) {
111+ check_obj_space(1);
112+ g_object[g_objpos++]=i;
113+ shift=0;
114+ i=0;
115+ }
116+ next_position();
117+ b1=g_source[g_srcpos];
118+ if (b1!=',') break;
119+ g_srcpos++;
120+ next_position();
121+ b1=g_source[g_srcpos];
122+ if (b1==0x0d || b1==0x0a) {
123+ // Multiline CDATA statement
124+ g_line++;
125+ g_fileline++;
126+ if (b1==0x0D && g_source[g_srcpos+1]==0x0A) g_srcpos++;
127+ g_srcpos++;
128+ // Maintain at least 256 characters in cache.
129+ if (256<=g_srcpos) read_file(256);
130+ next_position();
131+ b1=g_source[g_srcpos];
132+ }
133+ }
134+ // Write the last 1-3 bytes and shift data if total # is not multipes of 4.
135+ if (0<shift) {
136+ // Convert shift value from bit-shift to data byte-shift.
137+ shift=4-shift/8;
138+ check_obj_space(1);
139+ g_object[g_objpos++]=i;
140+ for(cpy=(char*)&g_object[g_objpos]-1;(char*)&g_object[beginpos+2]<cpy;cpy--){
141+ cpy[0]=cpy[0-shift];
142+ }
143+ }
144+ // Determine the size of data
145+ i=g_objpos-beginpos-1;
146+ g_object[beginpos] =0x04110000|i; // bgezal zero,xxxx
147+ g_object[beginpos+1]=0x00000020|shift; // add zero,zero,zero
148+ return 0;
149+}
150+
151+char* data_statement(){
152+ // 0x00000020, 0x00000021, 0x00000022, and 0x00000023 (add/addu/sub/subu zero,zero,zero)
153+ // are the sign of data region
154+ int i,prevpos;
155+ char* err;
156+ while(1){
157+ prevpos=g_objpos;
158+ check_obj_space(2);
159+ g_object[g_objpos++]=0x04110000; // bgezal zero,xxxx
160+ g_object[g_objpos++]=0x00000020; // add zero,zero,zero
161+ next_position();
162+ if (g_source[g_srcpos]=='"') {
163+ // Constant string
164+ // Store pointer to string. This is 3 words bellow of current position
165+ g_object[g_objpos]=(int)(&g_object[g_objpos+3]);
166+ g_objpos++;
167+ g_object[prevpos]=0x04110002; // bgezal zero,xxxx
168+ err=simple_string();
169+ if (err) return err;
170+ next_position();
171+ if (g_source[g_srcpos]==',') continue;
172+ return 0;
173+ }
174+ err=exec_statement();
175+ if (err) return err;
176+ // Determine the size of data
177+ i=g_objpos-prevpos-1;
178+ g_object[prevpos]=0x04110000|i; // bgezal zero,xxxx
179+ if (g_source[g_srcpos]=='"') {
180+ // Constant string
181+ continue;
182+ }
183+ return 0;
184+ }
185+}
186+
187+char* clear_statement(){
188+ call_lib_code(LIB_CLEAR);
189+ return 0;
190+}
191+
192+char* poke_statement(){
193+ char* err;
194+ err=get_value();
195+ if (err) return err;
196+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
197+ g_srcpos++;
198+ check_obj_space(2);
199+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
200+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
201+ err=get_value();
202+ if (err) return err;
203+ check_obj_space(3);
204+ g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp)
205+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
206+ g_object[g_objpos++]=0xA0620000; // sb v0,0(v1)
207+ return 0;
208+}
209+
210+char* dim_statement(){
211+ char* err;
212+ char b1;
213+ int spos;
214+ int stack;
215+ while(1){
216+ stack=0;
217+ next_position();
218+ b1=g_source[g_srcpos];
219+ if (b1<'A' || 'Z'<b1) return ERR_SYNTAX;
220+ g_srcpos++;
221+ if (g_source[g_srcpos]=='#') g_srcpos++;
222+ next_position();
223+ if (g_source[g_srcpos]!='(') return ERR_SYNTAX;
224+ check_obj_space(1);
225+ spos=g_objpos++; // addiu sp,sp,xxxx
226+ do {
227+ g_srcpos++;
228+ err=get_value();
229+ if (err) return err;
230+ stack+=4;
231+ check_obj_space(1);
232+ g_object[g_objpos++]=0xAFA20000|stack; // sw v0,8(sp)
233+ } while (g_source[g_srcpos]==',');
234+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
235+ g_srcpos++;
236+ check_obj_space(3);
237+ g_object[g_objpos++]=0x24040000|(b1-'A'); // addiu a0,zero,xx
238+ g_object[g_objpos++]=0x24050000|(stack/4); // addiu a1,zero,xxxx
239+ g_object[g_objpos++]=0x03A01025; // or v0,sp,zero
240+ call_lib_code(LIB_DIM);
241+ // Stack -/+
242+ check_obj_space(1);
243+ g_object[g_objpos++]=0x27BD0000|stack; // addiu sp,sp,xxxx
244+ stack=(0-stack)&0x0000FFFF;
245+ g_object[spos]=0x27BD0000|stack; // addiu sp,sp,xxxx
246+ next_position();
247+ if (g_source[g_srcpos]!=',') break;
248+ g_srcpos++;
249+ }
250+ return 0;
251+}
252+
253+char* label_statement(){
254+ char* err;
255+ char b1;
256+ b1=g_source[g_srcpos];
257+ if (b1<'A' || 'Z'<b1) return ERR_SYNTAX; // Number is not allowed here.
258+ err=get_label();
259+ if (err) return err;
260+ // Check existing label with the same name here.
261+ if (search_label(g_label)) {
262+ // Error: duplicate labels
263+ printstr("Label ");
264+ printstr(resolve_label(g_label));
265+ return ERR_MULTIPLE_LABEL;
266+ }
267+ check_obj_space(2);
268+ g_object[g_objpos++]=0x3C160000|((g_label>>16)&0x0000FFFF); //lui s6,yyyy;
269+ g_object[g_objpos++]=0x36D60000|(g_label&0x0000FFFF); //ori s6,s6,zzzz;
270+ return 0;
271+}
272+
273+char* restore_statement(){
274+ char* err;
275+ err=get_label();
276+ if (err) return err;
277+ if (g_label) {
278+ // Constant label/number
279+ // Use 32 bit mode also for values<65536
280+ // This code will be replaced to code for v0 for pointer in linker.
281+ check_obj_space(2);
282+ g_object[g_objpos++]=0x3C020000|(g_label>>16); // lui v0,xxxx
283+ g_object[g_objpos++]=0x34420000|(g_label&0x0000FFFF); // ori v0,v0,xxxx
284+ } else {
285+ // Dynamic number
286+ err=get_value();
287+ if (err) return err;
288+ }
289+ call_lib_code(LIB_RESTORE);
290+ return 0;
291+}
292+
293+char* gosub_statement_sub(){
294+ char* err;
295+ err=get_label();
296+ if (err) return err;
297+ if (g_label) {
298+ // Label/number is constant.
299+ // Linker will change following codes later.
300+ // Note that 0x0812xxxx and 0x0813xxxx are specific codes for these.
301+ check_obj_space(6);
302+ g_object[g_objpos++]=0x04110003; // bgezal zero,label1
303+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
304+ g_object[g_objpos++]=0x10000003; // beq zero,zero,label2
305+ g_object[g_objpos++]=0x08120000|((g_label>>16)&0x0000FFFF); // nop
306+ // label1:
307+ g_object[g_objpos++]=0x08130000|(g_label&0x0000FFFF); // j xxxx
308+ g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp)
309+ // label2:
310+ } else {
311+ // Label/number will be dynamically set when executing code.
312+ err=get_value();
313+ if (err) return err;
314+ call_lib_code(LIB_LABEL);
315+ check_obj_space(6);
316+ g_object[g_objpos++]=0x04110003; // bgezal zero,label1
317+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
318+ g_object[g_objpos++]=0x10000003; // beq zero,zero,label2
319+ g_object[g_objpos++]=0x00000000; // nop
320+ // label1:
321+ g_object[g_objpos++]=0x00400008; // jr v0
322+ g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp)
323+ // label2:
324+ }
325+ return 0;
326+}
327+
328+char* gosub_statement(){
329+ char* err;
330+ int opos,spos,stack;
331+ opos=g_objpos;
332+ spos=g_srcpos;
333+ err=gosub_statement_sub();
334+ if (err) return err;
335+ next_position();
336+ // If there is no 2nd argument, return.
337+ if (g_source[g_srcpos]!=',') return 0;
338+
339+ // There is (at least) 2nd argument.
340+ // Rewind object and construct argument-creating routine.
341+ g_objpos=opos;
342+ stack=4;
343+ g_object[g_objpos++]=0x27BD0000; // addiu sp,sp,-xx
344+ do {
345+ g_srcpos++;
346+ stack+=4;
347+ err=get_stringFloatOrValue();
348+ if (err) return err;
349+ check_obj_space(1);
350+ g_object[g_objpos++]=0xAFA20000|stack; // sw v0,xx(sp)
351+ next_position();
352+ } while(g_source[g_srcpos]==',');
353+ check_obj_space(2);
354+ g_object[g_objpos++]=0xAFB50004; // sw s5,4(sp)
355+ g_object[g_objpos++]=0x03A0A821; // addu s5,sp,zero
356+ g_object[opos]|=((0-stack)&0xFFFF); // addiu sp,sp,-xx (See above)
357+ // Rewind source and construct GOSUB routine again.
358+ opos=spos;
359+ spos=g_srcpos;
360+ g_srcpos=opos;
361+ err=gosub_statement_sub();
362+ if (err) return err;
363+ // Remove stack
364+ check_obj_space(2);
365+ g_object[g_objpos++]=0x8FB50004; // lw s5,4(sp)
366+ g_object[g_objpos++]=0x27BD0000|stack; // addiu sp,sp,xx
367+ // All done, go back to wright source position
368+ g_srcpos=spos;
369+ return 0;
370+}
371+
372+char* return_statement(){
373+ char* err;
374+ char b1;
375+ next_position();
376+ b1=g_source[g_srcpos];
377+ if (0x20<b1 && b1!=':') {
378+ // There is a return value.
379+ err=get_stringFloatOrValue();
380+ if (err) return err;
381+ }
382+ check_obj_space(3);
383+ g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp)
384+ g_object[g_objpos++]=0x00600008; // jr v1
385+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
386+ return 0;
387+}
388+
389+char* goto_statement(){
390+ char* err;
391+ err=get_label();
392+ if (err) return err;
393+ if (g_label) {
394+ // Label/number is constant.
395+ // Linker will change following codes later.
396+ // Note that 0x0810xxxx and 0x0811xxxx are specific codes for these.
397+ check_obj_space(2);
398+ g_object[g_objpos++]=0x08100000|((g_label>>16)&0x0000FFFF); // j xxxx
399+ g_object[g_objpos++]=0x08110000|(g_label&0x0000FFFF); // nop
400+ } else {
401+ // Label/number will be dynamically set when executing code.
402+ err=get_value();
403+ if (err) return err;
404+ call_lib_code(LIB_LABEL);
405+ check_obj_space(2);
406+ g_object[g_objpos++]=0x00400008; // jr v0
407+ g_object[g_objpos++]=0x00000000; // nop
408+ }
409+ return 0;
410+}
411+
412+char* if_statement(){
413+ char* err;
414+ int prevpos,bpos;
415+ // Get value.
416+ err=get_floatOrValue();
417+ if (err) return err;
418+ // Check "THEN"
419+ if (!nextCodeIs("THEN")) return ERR_SYNTAX;
420+ // Check if statement follows after THEN statement
421+ next_position();
422+ if (nextCodeIs("REM")) {
423+ // If REM statement follows, skip comment words.
424+ rem_statement();
425+ }
426+ if (g_source[g_srcpos]<0x20) {
427+ // End of line.
428+ // Use IF-THEN-ENDIF mode (multiple line mode)
429+ check_obj_space(3);
430+ g_object[g_objpos++]=0x30000000; // nop (see linker)
431+ g_object[g_objpos++]=0x10400000; // beq v0,zero,xxxx
432+ g_object[g_objpos++]=0x30000000; // nop (see linker)
433+ return 0;
434+ }
435+ // One line mode
436+ // If $v0=0 then skip.
437+ bpos=g_objpos;
438+ check_obj_space(2);
439+ g_object[g_objpos++]=0x10400000; // beq v0,zero,xxxx
440+ g_object[g_objpos++]=0x00000000; // nop
441+ prevpos=g_srcpos;
442+ if (statement()) {
443+ // May be label
444+ g_srcpos=prevpos;
445+ err=goto_statement();
446+ if (err) return err;
447+ } else {
448+ // Must be statement(s)
449+ while(1) {
450+ if (g_source[g_srcpos]!=':') break;
451+ g_srcpos++;
452+ err=statement();
453+ if (err) return err;
454+ }
455+ }
456+ // Check if "ELSE" exists.
457+ if (!nextCodeIs("ELSE ")) {
458+ // "ELSE" not found. This is the end of "IF" statement.
459+ // Previous branch command must jump to this position.
460+ g_object[bpos]=0x10400000|(g_objpos-bpos-1); // beq v0,zero,xxxx
461+ return 0;
462+ }
463+ // Skip after ELSE if required.
464+ check_obj_space(2);
465+ g_object[g_objpos++]=0x10000000; // beq zero,zero,xxxx
466+ g_object[g_objpos++]=0x00000000; // nop
467+ // Previous branch command must jump to this position.
468+ g_object[bpos]=0x10400000|(g_objpos-bpos-1); // beq v0,zero,xxxx
469+ bpos=g_objpos-2;
470+ // Next statement is either label or general statement
471+ prevpos=g_srcpos;
472+ if (statement()) {
473+ // May be label
474+ g_srcpos=prevpos;
475+ err=goto_statement();
476+ if (err) return err;
477+ } else {
478+ // Must be statement(s)
479+ while(1) {
480+ if (g_source[g_srcpos]!=':') break;
481+ g_srcpos++;
482+ err=statement();
483+ if (err) return err;
484+ }
485+ }
486+ // Previous branch command must jump to this position.
487+ g_object[bpos]=0x10000000|(g_objpos-bpos-1); // beq zero,zero,xxxx
488+ return 0;
489+}
490+
491+char* elseif_statement(void){
492+ // Multiple line mode
493+ char* err;
494+ g_object[g_objpos++]=0x08160100; // breakif (see linker)
495+ g_object[g_objpos++]=0x30008000; // nop (see linker)
496+ // Get value.
497+ err=get_floatOrValue();
498+ if (err) return err;
499+ // Check "THEN"
500+ if (!nextCodeIs("THEN")) return ERR_SYNTAX;
501+ // Check if statement follows after THEN statement
502+ next_position();
503+ if (nextCodeIs("REM")) {
504+ // If REM statement follows, skip comment words.
505+ rem_statement();
506+ }
507+ if (0x20<=g_source[g_srcpos]) return ERR_SYNTAX;
508+ // Statement didn't follow after THEM statement (that is correct).
509+ g_object[g_objpos++]=0x10400000; // beq v0,zero,xxxx
510+ g_object[g_objpos++]=0x30000000; // nop (see linker)
511+ return 0;
512+
513+}
514+
515+char* else_statement(void){
516+ // Multiple line mode
517+ g_object[g_objpos++]=0x08160100; // breakif (see linker)
518+ g_object[g_objpos++]=0x30008000; // nop (see linker)
519+ g_object[g_objpos++]=0x30000000; // nop (see linker)
520+ // Check if statement follows after THEN statement
521+ next_position();
522+ if (nextCodeIs("REM")) {
523+ // If REM statement follows, skip comment words.
524+ rem_statement();
525+ }
526+ if (0x20<=g_source[g_srcpos]) return ERR_SYNTAX;
527+ // Statement didn't follow after THEM statement (that is correct).
528+ return 0;
529+}
530+
531+char* endif_statement(void){
532+ // Multiple line mode
533+ g_object[g_objpos++]=0x30008000; // nop (see linker)
534+ g_object[g_objpos++]=0x30008000; // nop (see linker)
535+ // Check if statement follows after THEN statement
536+ next_position();
537+ if (nextCodeIs("REM")) {
538+ // If REM statement follows, skip comment words.
539+ rem_statement();
540+ }
541+ if (0x20<=g_source[g_srcpos]) return ERR_SYNTAX;
542+ // Statement didn't follow after THEM statement (that is correct).
543+ return 0;
544+}
545+
546+char* end_statement(void){
547+ int i;
548+ i=(int)&g_end_addr;
549+ i-=g_gp;
550+ check_obj_space(3);
551+ g_object[g_objpos++]=0x8F820000|(i&0x0000FFFF); // lw v0,xxxx(gp)
552+ g_object[g_objpos++]=0x00400008; // jr v0
553+ g_object[g_objpos++]=0x00000000; // nop
554+ return 0;
555+}
556+
557+char* let_dim_sub(char b1){
558+ char* err;
559+ g_srcpos++;
560+ err=get_value();
561+ if (err) return err;
562+ check_obj_space(4);
563+ g_object[g_objpos++]=0x00021080; // sll v0,v0,0x2
564+ g_object[g_objpos++]=0x8FC30000|((b1-'A')*4); // lw v1,xx(s8)
565+ g_object[g_objpos++]=0x00621821; // addu v1,v1,v0
566+ g_object[g_objpos++]=0xAFA30004; // sw v1,4(sp)
567+ while(g_source[g_srcpos]==','){
568+ g_srcpos++;
569+ err=get_value();
570+ if (err) return err;
571+ check_obj_space(4);
572+ g_object[g_objpos++]=0x00021080; // sll v0,v0,0x2
573+ g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp)
574+ g_object[g_objpos++]=0x8C630000; // lw v1,0(v1)
575+ g_object[g_objpos++]=0x00621821; // addu v1,v1,v0
576+ g_object[g_objpos++]=0xAFA30004; // sw v1,4(sp)
577+ }
578+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
579+ g_srcpos++;
580+ return 0;
581+};
582+
583+char* let_statement(){
584+ char* err;
585+ char b1,b2,b3;
586+ int i;
587+ next_position();
588+ b1=g_source[g_srcpos];
589+ b2=g_source[g_srcpos+1];
590+ b3=g_source[g_srcpos+2];
591+ if (b1<'A' || 'Z'<b1) return ERR_SYNTAX;
592+ g_srcpos++;
593+ if (b2=='#' && b3=='(') {
594+ // Float dimension
595+ g_srcpos++;
596+ check_obj_space(1);
597+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
598+ let_dim_sub(b1);
599+ next_position();
600+ if (g_source[g_srcpos]!='=') return ERR_SYNTAX;
601+ g_srcpos++;
602+ err=get_float();
603+ if (err) return err;
604+ check_obj_space(3);
605+ g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp)
606+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
607+ g_object[g_objpos++]=0xAC620000; // sw v0,0(v1)
608+ return 0;
609+ } else if (b2=='#') {
610+ // Float A-Z
611+ g_srcpos++;
612+ next_position();
613+ if (g_source[g_srcpos]!='=') return ERR_SYNTAX;
614+ g_srcpos++;
615+ err=get_float();
616+ if (err) return err;
617+ check_obj_space(1);
618+ g_object[g_objpos++]=0xAFC20000|((b1-'A')*4); // sw v0,xxx(s8)
619+ return 0;
620+ } else if (b2=='$') {
621+ // String
622+ g_srcpos++;
623+ next_position();
624+ if (g_source[g_srcpos]!='=') return ERR_SYNTAX;
625+ g_srcpos++;
626+ err=get_string();
627+ if (err) return err;
628+ check_obj_space(1);
629+ g_object[g_objpos++]=0x24040000|(b1-'A'); //addiu a0,zero,xx
630+ call_lib_code(LIB_LETSTR);
631+ return 0;
632+ } else if (b2=='(') {
633+ // Dimension
634+ check_obj_space(1);
635+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
636+ let_dim_sub(b1);
637+ next_position();
638+ if (g_source[g_srcpos]!='=') return ERR_SYNTAX;
639+ g_srcpos++;
640+ err=get_value();
641+ if (err) return err;
642+ check_obj_space(3);
643+ g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp)
644+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
645+ g_object[g_objpos++]=0xAC620000; // sw v0,0(v1)
646+ return 0;
647+ } else {
648+ // Integer A-Z
649+ next_position();
650+ if (g_source[g_srcpos]!='=') return ERR_SYNTAX;
651+ g_srcpos++;
652+ err=get_value();
653+ if (err) return err;
654+ check_obj_space(1);
655+ g_object[g_objpos++]=0xAFC20000|((b1-'A')*4); // sw v0,xxx(s8)
656+ }
657+ return 0;
658+}
659+
660+char* print_statement(){
661+ char* err;
662+ char b1;
663+ int i;
664+ int status=0;// 1:',' 2:';' 0:none
665+ while(1){
666+ next_position();
667+ b1=g_source[g_srcpos];
668+ if (b1<0x20 || b1==':') break;
669+ if (!strncmp(g_source+g_srcpos,"ELSE " ,5)) break;
670+ err=get_stringFloatOrValue();
671+ if (err) return err;
672+ switch(g_lastvar){
673+ case VAR_INTEGER:
674+ // Use DEC$() function.
675+ call_lib_code(LIB_DEC);
676+ break;
677+ case VAR_FLOAT:
678+ // Use FLOAT$() function.
679+ check_obj_space(2);
680+ g_object[g_objpos++]=0x00022021; //addu a0,zero,v0
681+ g_object[g_objpos++]=0x34020000; //ori v0,zero,0x0000
682+ call_lib_code(LIB_SPRINTF);
683+ break;
684+ case VAR_STRING:
685+ default:
686+ break;
687+ }
688+ // Call printstr() function
689+ // First argument is the pointer to string
690+ call_lib_code(LIB_PRINTSTR);
691+ next_position();
692+ b1=g_source[g_srcpos];
693+ if (b1==',') {
694+ status=1;
695+ g_srcpos++;
696+ // Call lib_string() function for comma (,)
697+ check_obj_space(1);
698+ g_object[g_objpos++]=0x34040001; // ori a0,zero,1
699+ call_lib_code(LIB_STRING);
700+ } else if (b1==';') {
701+ status=2;
702+ g_srcpos++;
703+ } else {
704+ status=0;
705+ }
706+ }
707+ if (status==0) {
708+ // Call lib_string() function for CR (\n)
709+ check_obj_space(1);
710+ g_object[g_objpos++]=0x34040000; // ori a0,zero,0
711+ call_lib_code(LIB_STRING);
712+ }
713+ return 0;
714+}
715+
716+char* break_statement(){
717+ check_obj_space(2);
718+ g_object[g_objpos++]=0x08160000; // j xxxx (See link() function)
719+ g_object[g_objpos++]=0x00000000; // nop
720+ return 0;
721+}
722+
723+char* for_statement(){
724+ char* err;
725+ char b1;
726+ // Initialization of variable
727+ next_position();
728+ b1=g_source[g_srcpos];
729+ if (b1<'A' || 'Z'<b1) return ERR_SYNTAX;
730+ err=let_statement();
731+ if (err) return err;
732+ // Check if "TO" exists
733+ next_position();
734+ if (!nextCodeIs("TO ")) return ERR_SYNTAX;
735+ err=get_value();
736+ if (err) return err;
737+ // Usage of stack:
738+ // 12(sp): "TO" value
739+ // 8(sp): "STEP" value
740+ // 4(sp): Address to return to in "NEXT" statement.
741+ // Store "TO" value in stack
742+ check_obj_space(2);
743+ g_object[g_objpos++]=0x0820FFF4; // addiu sp,sp,-12 (see linker)
744+ g_object[g_objpos++]=0xAFA2000C; // sw v0,12(sp)
745+ // Check if "STEP" exists
746+ next_position();
747+ g_valueisconst=1;
748+ if (nextCodeIs("STEP ")) {
749+ // "STEP" exists. Get value
750+ err=get_value();
751+ if (err) return err;
752+ } else {
753+ // "STEP" not exist. Use "1".
754+ check_obj_space(1);
755+ g_object[g_objpos++]=0x24020001; // addiu v0,zero,1
756+ g_intconst=1;
757+ }
758+ check_obj_space(14);
759+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp) (STEP value)
760+ g_object[g_objpos++]=0x04110004; // bgezal zero,check
761+ g_object[g_objpos++]=0x8FC40000|((b1-'A')*4); // lw a0,xx(s8) (current var value)
762+ // After executing "NEXT" statement, process reaches following line.
763+ // Update variable value by adding STEP value
764+ // Note that STEP value is loaded onto $v0 in NEXT statement
765+ g_object[g_objpos++]=0x8FC40000|((b1-'A')*4); // lw a0,xx(s8) (current var value)
766+ g_object[g_objpos++]=0x00822021; // addu a0,a0,v0
767+ g_object[g_objpos++]=0xAFC40000|((b1-'A')*4); // sw a0,xx(s8) (new var value)
768+ // Value-checking routine and storing ra in stack
769+ // check:
770+ g_object[g_objpos++]=0x8FA3000C; // lw v1,12(sp) (TO value)
771+ g_object[g_objpos++]=0x00641823; // subu v1,v1,a0
772+ g_object[g_objpos++]=0x04420001; // bltzl v0,negative
773+ g_object[g_objpos++]=0x00031823; // subu v1,zero,v1
774+ // negative:
775+ g_object[g_objpos++]=0x04610003; // bgez v1,continue
776+ g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp)
777+ break_statement(); // (2 words)
778+ // continue:
779+ return 0;
780+}
781+
782+char* next_statement(){
783+ // Return to address stored in 4($sp)
784+ // while set $v0 to 8($sp) (see for_statement)
785+ check_obj_space(4);
786+ g_object[g_objpos++]=0x8FBF0004; // lw ra,4(sp)
787+ g_object[g_objpos++]=0x03E00008; // jr ra
788+ g_object[g_objpos++]=0x8FA20008; // lw v0,8(sp) (STEP value)
789+ g_object[g_objpos++]=0x0830000C; // addiu sp,sp,12 (see linker)
790+ return 0;
791+}
792+
793+char* do_statement(){
794+ char* err;
795+ // Usage of stack:
796+ // 4(sp): Address to return to in "DO" statement.
797+ check_obj_space(3);
798+ g_object[g_objpos++]=0x04110001;// bgezal zero,label1:
799+ g_object[g_objpos++]=0x0822FFFC;// addiu sp,sp,-4 (see linker)
800+ // label1:
801+ g_object[g_objpos++]=0xAFBF0004;// sw ra,4(sp)
802+ next_position();
803+ if (nextCodeIs("WHILE ")) {
804+ // DO WHILE
805+ err=get_floatOrValue();
806+ if (err) return err;
807+ check_obj_space(2);
808+ g_object[g_objpos++]=0x14400003; // bne v0,zero,labe2
809+ g_object[g_objpos++]=0x00000000; // nop
810+ return break_statement(); // (2 words)
811+ // label2:
812+
813+ } else if (nextCodeIs("UNTIL ")) {
814+ // DO UNTIL
815+ err=get_floatOrValue();
816+ if (err) return err;
817+ check_obj_space(2);
818+ g_object[g_objpos++]=0x10400003; // beq v0,zero,label2
819+ g_object[g_objpos++]=0x00000000; // nop
820+ return break_statement(); // (2 words)
821+ // label2:
822+ } else {
823+ // DO statement without WHILE/UNTIL
824+ return 0;
825+ }
826+}
827+
828+char* loop_statement(){
829+ char* err;
830+ next_position();
831+ if (nextCodeIs("WHILE ")) {
832+ // LOOP WHILE
833+ err=get_floatOrValue();
834+ if (err) return err;
835+ check_obj_space(1);
836+ g_object[g_objpos++]=0x10400003; // beq v0,zero,label1
837+ } else if (nextCodeIs("UNTIL ")) {
838+ // LOOP UNTIL
839+ err=get_floatOrValue();
840+ if (err) return err;
841+ check_obj_space(1);
842+ g_object[g_objpos++]=0x14400003; // bne v0,zero,label
843+ } else {
844+ // LOOP statement without WHILE/UNTIL
845+ }
846+ check_obj_space(4);
847+ g_object[g_objpos++]=0x8FBF0004; // lw ra,4(sp)
848+ g_object[g_objpos++]=0x03E00008; // jr ra
849+ g_object[g_objpos++]=0x00000000; // nop
850+ // label1:
851+ g_object[g_objpos++]=0x08320004; // addiu sp,sp,4 (See link() function)
852+ return 0;
853+}
854+
855+char* while_statement(){
856+ char* err;
857+ check_obj_space(3);
858+ g_object[g_objpos++]=0x04110001; // bgezal zero,label1:
859+ g_object[g_objpos++]=0x0821FFFC; // addiu sp,sp,-4 (see linker)
860+ // label1:
861+ g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp)
862+ err=get_floatOrValue();
863+ if (err) return err;
864+ check_obj_space(2);
865+ g_object[g_objpos++]=0x14400003; // bne v0,zero,label2
866+ g_object[g_objpos++]=0x00000000; // nop
867+ return break_statement(); // (2 words)
868+ // label2:
869+}
870+
871+char* wend_statement(){
872+ check_obj_space(4);
873+ g_object[g_objpos++]=0x8FBF0004; // lw ra,4(sp)
874+ g_object[g_objpos++]=0x03E00008; // jr ra
875+ g_object[g_objpos++]=0x00000000; // nop
876+ // label1:
877+ g_object[g_objpos++]=0x08310004; // addiu sp,sp,4 (See link() function)
878+ return 0;
879+}
880+
881+char* palette_statement(enum libs lib){
882+ // lib is either LIB_PALETTE or LIB_GPALETTE
883+ // PALETTE N,R,G,B
884+ char* err;
885+ // Get N
886+ err=get_value();
887+ if (err) return err;
888+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
889+ g_srcpos++;
890+ check_obj_space(2);
891+ g_object[g_objpos++]=0x27BDFFF4; // addiu sp,sp,-12
892+ g_object[g_objpos++]=0xAFA2000C; // sw v0,12(sp)
893+ // Get R
894+ err=get_value();
895+ if (err) return err;
896+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
897+ g_srcpos++;
898+ check_obj_space(1);
899+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
900+ // Get G
901+ err=get_value();
902+ if (err) return err;
903+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
904+ g_srcpos++;
905+ check_obj_space(1);
906+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
907+ // Get B
908+ err=get_value();
909+ if (err) return err;
910+ check_obj_space(6);
911+ g_object[g_objpos++]=0x8FA40008; // lw a0,8(sp)
912+ g_object[g_objpos++]=0x00042400; // sll a0,a0,0x10
913+ g_object[g_objpos++]=0x8FA50004; // lw a1,4(sp)
914+ g_object[g_objpos++]=0x00A42825; // or a1,a1,a0
915+ g_object[g_objpos++]=0x8FA4000C; // lw a0,12(sp)
916+ g_object[g_objpos++]=0x27BD000C; // addiu sp,sp,12
917+ // a0=N, a1=(R<<16)|G, v0=B
918+ call_lib_code(lib);
919+ return 0;
920+}
921+
922+char* param3_statement(enum libs lib){
923+ char* err;
924+ // Get 1st parameter
925+ err=get_value();
926+ if (err) return err;
927+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
928+ g_srcpos++;
929+ check_obj_space(2);
930+ g_object[g_objpos++]=0x27BDFFF8; // addiu sp,sp,-8
931+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
932+ // Get 2nd parameter
933+ err=get_value();
934+ if (err) return err;
935+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
936+ g_srcpos++;
937+ check_obj_space(1);
938+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
939+ // Get 3rd parameter
940+ err=get_value();
941+ if (err) return err;
942+ check_obj_space(3);
943+ g_object[g_objpos++]=0x8FA40008; // lw a0,8(sp)
944+ g_object[g_objpos++]=0x8FA50004; // lw a1,4(sp)
945+ g_object[g_objpos++]=0x27BD0008; // addiu sp,sp,8
946+ // a0=1st, a1=2nd, v0=3rd
947+ call_lib_code(lib);
948+ return 0;
949+}
950+
951+char* bgcolor_statement(){
952+ // BGCOLOR R,G,B
953+ return param3_statement(LIB_BGCOLOR);
954+}
955+
956+char* pcg_statement(){
957+ // PCG ASCII,D1,D2
958+ return param3_statement(LIB_PCG);
959+}
960+
961+char* usepcg_statement(){
962+ int objpos=g_objpos;
963+ if (get_value()) {
964+ // Getting integer failed.
965+ // It supporsed to be not parameter
966+ // and same as parameter=1.
967+ g_objpos=objpos;
968+ check_obj_space(1);
969+ g_object[g_objpos++]=0x34020001; //ori v0,zero,0x01
970+ }
971+ call_lib_code(LIB_USEPCG);
972+ return 0;
973+}
974+
975+char* usegraphic_statement(){
976+ int objpos=g_objpos;
977+ if (get_value()) {
978+ // Getting integer failed.
979+ // It supporsed to be not parameter
980+ // and same as parameter=1.
981+ g_objpos=objpos;
982+ check_obj_space(1);
983+ g_object[g_objpos++]=0x34020001; //ori v0,zero,0x01
984+ }
985+ call_lib_code(LIB_USEGRAPHIC);
986+ return 0;
987+}
988+
989+char* cls_statement(){
990+ call_lib_code(LIB_CLS);
991+ return 0;
992+}
993+
994+char* gcls_statement(){
995+ call_lib_code(LIB_GCLS);
996+ return 0;
997+}
998+
999+char* color_statement(){
1000+ char* err;
1001+ err=get_value();
1002+ if (err) return err;
1003+ call_lib_code(LIB_COLOR);
1004+ return 0;
1005+}
1006+
1007+char* gcolor_statement(){
1008+ char* err;
1009+ err=get_value();
1010+ if (err) return err;
1011+ call_lib_code(LIB_GCOLOR);
1012+ return 0;
1013+}
1014+
1015+char* param2_statement(enum libs lib){
1016+ char* err;
1017+ // Get 1st
1018+ err=get_value();
1019+ if (err) return err;
1020+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1021+ g_srcpos++;
1022+ check_obj_space(2);
1023+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
1024+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
1025+ // Get 2nd
1026+ err=get_value();
1027+ if (err) return err;
1028+ check_obj_space(2);
1029+ g_object[g_objpos++]=0x8FA40004; // lw a0,4(sp)
1030+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
1031+ call_lib_code(lib);
1032+ return 0;
1033+}
1034+
1035+char* system_statement(){
1036+ // SYSTEM X,Y
1037+ return param2_statement(LIB_SYSTEM);
1038+}
1039+
1040+char* cursor_statement(){
1041+ // CURSOR X,Y
1042+ return param2_statement(LIB_CURSOR);
1043+}
1044+
1045+char* scroll_statement(){
1046+ // SCROLL X,Y
1047+ return param2_statement(LIB_SCROLL);
1048+}
1049+
1050+char* drawcount_statement(){
1051+ char* err;
1052+ err=get_value();
1053+ if (err) return err;
1054+ call_lib_code(LIB_SETDRAWCOUNT);
1055+ return 0;
1056+}
1057+
1058+char* wait_statement(){
1059+ char* err;
1060+ err=get_value();
1061+ if (err) return err;
1062+ call_lib_code(LIB_WAIT);
1063+ return 0;
1064+}
1065+char* var_statement(){
1066+ // Clear flags
1067+ unsigned int flags=0;
1068+ // Prepare stack
1069+ // Note that 12 bytes is used in lib_var()
1070+ // Another 4 bytes is used for return address
1071+ short stack=12;
1072+ char b;
1073+ do {
1074+ // Seek variable
1075+ next_position();
1076+ b=g_source[g_srcpos++];
1077+ if (b<'A' || 'Z'<b) return ERR_SYNTAX;
1078+ flags|=1<<(b-'A');
1079+ stack+=4;
1080+ // Support float and string variables
1081+ b=g_source[g_srcpos];
1082+ if (b=='#' || b=='$') g_srcpos++;
1083+ // Seek ',' or end of statement
1084+ next_position();
1085+ b=g_source[g_srcpos++];
1086+ } while(b==',');
1087+ g_srcpos--;
1088+ // Jump to push routine, first
1089+ check_obj_space(2);
1090+ g_object[g_objpos++]=0x04110007; // bgezal zero,label1
1091+ g_object[g_objpos++]=0x27BD0000|((0-stack)&0xffff); // addiu sp,sp,-xx
1092+ // Process will be here after RETURN statement
1093+ // Pop routine
1094+ check_obj_space(1);
1095+ g_object[g_objpos++]=0x03A02821; // addu a1,sp,zero
1096+ call_lib_code(LIB_VAR_POP);
1097+ // Restore stack and return
1098+ check_obj_space(4);
1099+ g_object[g_objpos++]=0x8FA30000|stack; // lw v1,xx(sp)
1100+ g_object[g_objpos++]=0x00600008; // jr v1
1101+ g_object[g_objpos++]=0x27BD0000|stack; // addiu sp,sp,xx
1102+ // Push rotine
1103+ check_obj_space(4); // label1:
1104+ g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp)
1105+ g_object[g_objpos++]=0x03A02821; // addu a1,sp,zero
1106+ g_object[g_objpos++]=0x3C040000|(flags>>16); // lui a0,XXXX
1107+ g_object[g_objpos++]=0x34840000|(flags&0xffff); // ori a0,a0,XXXX
1108+ call_lib_code(LIB_VAR_PUSH);
1109+ return 0;
1110+}
1111+
1112+char* graphic_statement(enum functions func){
1113+ /*
1114+ PSET X1,Y1[,C]
1115+ LINE X1,Y1,X2,Y2[,C]
1116+ BOXFILL X1,Y1,X2,Y2[,C]
1117+ CIRCLE X1,Y1,R[,C]
1118+ CIRCLEFILL X1,Y1,R[,C]
1119+ GPRINT X1,Y1,C,BC,S$
1120+ PUTBMP X1,Y1,M,N,BMP
1121+ $a0 cotains func (8 bits), X1 (12 bits) and Y1 (12 bits)
1122+ $a1 contains X2/R (12 bits) and Y2 (12 bits)
1123+ $v0 contains C/S$/BMP (32 bits)
1124+ */
1125+ char* err;
1126+ int paramnum;
1127+ switch(func){
1128+ case FUNC_PSET:// X1,Y1[,C]
1129+ case FUNC_GCOLOR:// X1,Y1
1130+ case FUNC_POINT:// X1,Y1
1131+ paramnum=2;
1132+ break;
1133+ case FUNC_CIRCLE:// X1,Y1,R[,C]
1134+ case FUNC_CIRCLEFILL:// X1,Y1,R[,C]
1135+ paramnum=3;
1136+ break;
1137+ case FUNC_LINE:// X1,Y1,X2,Y2[,C]
1138+ case FUNC_BOXFILL:// X1,Y1,X2,Y2[,C]
1139+ paramnum=4;
1140+ break;
1141+ case FUNC_GPRINT:// X1,Y1,C,BC,S$
1142+ case FUNC_PUTBMP:// X1,Y1,M,N,BMP
1143+ paramnum=5;
1144+ break;
1145+ default:
1146+ return ERR_UNKNOWN;
1147+ }
1148+
1149+ next_position();
1150+ if (g_source[g_srcpos]==',') {
1151+ // X1 and Y1 is omitted. Set 0x800 for both.
1152+ check_obj_space(4);
1153+ g_object[g_objpos++]=0x27BDFFF8; // addiu sp,sp,-8
1154+ g_object[g_objpos++]=0x3C020080; // lui v0,0x0080
1155+ g_object[g_objpos++]=0x34420800; // ori v0,v0,0x0800
1156+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
1157+ } else {
1158+ // X1
1159+ err=get_value();
1160+ if (err) return err;
1161+ check_obj_space(4);
1162+ g_object[g_objpos++]=0x27BDFFF8; // addiu sp,sp,-8
1163+ g_object[g_objpos++]=0x30420FFF; // andi v0,v0,0xfff
1164+ g_object[g_objpos++]=0x00021300; // sll v0,v0,0xc
1165+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
1166+ // Y1
1167+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1168+ g_srcpos++;
1169+ err=get_value();
1170+ if (err) return err;
1171+ check_obj_space(4);
1172+ g_object[g_objpos++]=0x30420FFF; // andi v0,v0,0xfff
1173+ g_object[g_objpos++]=0x8FA40004; // lw a0,4(sp)
1174+ g_object[g_objpos++]=0x00441025; // or v0,v0,a0
1175+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
1176+ }
1177+ if (2<paramnum) {
1178+ // X2, R, or M
1179+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1180+ g_srcpos++;
1181+ err=get_value();
1182+ if (err) return err;
1183+ check_obj_space(3);
1184+ g_object[g_objpos++]=0x30420FFF; // andi v0,v0,0xfff
1185+ g_object[g_objpos++]=0x00021300; // sll v0,v0,0xc
1186+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
1187+ if (3<paramnum) {
1188+ // X2, BC, or N
1189+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1190+ g_srcpos++;
1191+ err=get_value();
1192+ if (err) return err;
1193+ check_obj_space(4);
1194+ g_object[g_objpos++]=0x30420FFF; // andi v0,v0,0xfff
1195+ g_object[g_objpos++]=0x8FA40008; // lw a0,8(sp)
1196+ g_object[g_objpos++]=0x00441025; // or v0,v0,a0
1197+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
1198+ }
1199+ }
1200+ if (func==FUNC_GPRINT) {
1201+ // S$
1202+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1203+ g_srcpos++;
1204+ err=get_string();
1205+ if (err) return err;
1206+ } else if (func==FUNC_PUTBMP) {
1207+ // BMP
1208+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1209+ g_srcpos++;
1210+ err=get_label();
1211+ if (g_label && !err) {
1212+ // Label/number is constant.
1213+ // Linker will change following codes later.
1214+ // Note that 0x0814xxxx and 0x0815xxxx are specific codes for these.
1215+ check_obj_space(2);
1216+ g_object[g_objpos++]=0x08140000|((g_label>>16)&0x0000FFFF); // lui v0,xxxx
1217+ g_object[g_objpos++]=0x08150000|(g_label&0x0000FFFF); // ori v0,v0,xxxx
1218+ // Change func to FUNC_PUTBMP2 (label mode).
1219+ func=FUNC_PUTBMP2;
1220+ } else {
1221+ err=get_value();
1222+ if (err) return err;
1223+ }
1224+ } else {
1225+ // [,C]
1226+ if (g_source[g_srcpos]==',') {
1227+ g_srcpos++;
1228+ err=get_value();
1229+ if (err) return err;
1230+ } else {
1231+ // If C is omitted, use -1.
1232+ check_obj_space(1);
1233+ g_object[g_objpos++]=0x2402FFFF; // addiu v0,zero,-1
1234+ }
1235+ }
1236+ // Prepare $a0
1237+ check_obj_space(1);
1238+ g_object[g_objpos++]=0x34040000|(func&0x0ff); // ori a0,zero,xxxx
1239+ g_object[g_objpos++]=0x00042600; // sll a0,a0,0x18
1240+ g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp)
1241+ g_object[g_objpos++]=0x00832025; // or a0,a0,v1
1242+ // Prepare $a1
1243+ g_object[g_objpos++]=0x8FA50008; // lw a1,8(sp)
1244+ // Restore stack pointer
1245+ g_object[g_objpos++]=0x27BD0008; // addiu sp,sp,8
1246+ // Call library
1247+ call_lib_code(LIB_GRAPHIC);
1248+ return 0;
1249+}
1250+#ifdef __DEBUG
1251+ char* debug_statement(){
1252+ call_lib_code(LIB_DEBUG);
1253+ return 0;
1254+ }
1255+#endif
1256+
1257+
1258+char* statement(void){
1259+ char* err;
1260+ int prevpos;
1261+ next_position();
1262+ // Clear flag for temp area usage.
1263+ g_temp_area_used=0;
1264+ // Initialize stack handler used for value
1265+ g_sdepth=g_maxsdepth=0;
1266+ if (nextCodeIs("REM")) {
1267+ err=rem_statement();
1268+ } else if (nextCodeIs("SOUND ")) {
1269+ err=sound_statement();
1270+ } else if (nextCodeIs("MUSIC ")) {
1271+ err=music_statement();
1272+ } else if (nextCodeIs("DRAWCOUNT ")) {
1273+ err=drawcount_statement();
1274+ } else if (nextCodeIs("CURSOR ")) {
1275+ err=cursor_statement();
1276+ } else if (nextCodeIs("PALETTE ")) {
1277+ err=palette_statement(LIB_PALETTE);
1278+ } else if (nextCodeIs("GPALETTE ")) {
1279+ err=palette_statement(LIB_GPALETTE);
1280+ } else if (nextCodeIs("BGCOLOR ")) {
1281+ err=bgcolor_statement();
1282+ } else if (nextCodeIs("CLS")) {
1283+ err=cls_statement();
1284+ } else if (nextCodeIs("GCLS")) {
1285+ err=gcls_statement();
1286+ } else if (nextCodeIs("COLOR ")) {
1287+ err=color_statement();
1288+ } else if (nextCodeIs("GCOLOR ")) {
1289+ err=gcolor_statement();
1290+ } else if (nextCodeIs("RESTORE ")) {
1291+ err=restore_statement();
1292+ } else if (nextCodeIs("DATA ")) {
1293+ err=data_statement();
1294+ } else if (nextCodeIs("CDATA ")) {
1295+ err=cdata_statement();
1296+ } else if (nextCodeIs("LABEL ")) {
1297+ err=label_statement();
1298+ } else if (nextCodeIs("DIM ")) {
1299+ err=dim_statement();
1300+ } else if (nextCodeIs("CLEAR")) {
1301+ err=clear_statement();
1302+ } else if (nextCodeIs("PRINT")) {
1303+ err=print_statement();
1304+ } else if (nextCodeIs("IF ")) {
1305+ err=if_statement();
1306+ } else if (nextCodeIs("ELSEIF ")) {
1307+ err=elseif_statement();
1308+ } else if (nextCodeIs("ELSE")) {
1309+ err=else_statement();
1310+ } else if (nextCodeIs("ENDIF")) {
1311+ err=endif_statement();
1312+ } else if (nextCodeIs("END")) {
1313+ err=end_statement();
1314+ } else if (nextCodeIs("EXEC ")) {
1315+ err=exec_statement();
1316+ } else if (nextCodeIs("GOTO ")) {
1317+ err=goto_statement();
1318+ } else if (nextCodeIs("GOSUB ")) {
1319+ err=gosub_statement();
1320+ } else if (nextCodeIs("RETURN")) {
1321+ err=return_statement();
1322+ } else if (nextCodeIs("POKE ")) {
1323+ err=poke_statement();
1324+ } else if (nextCodeIs("FOR ")) {
1325+ err=for_statement();
1326+ } else if (nextCodeIs("NEXT")) {
1327+ err=next_statement();
1328+ } else if (nextCodeIs("LET ")) {
1329+ err=let_statement();
1330+ } else if (nextCodeIs("PCG ")) {
1331+ err=pcg_statement();
1332+ } else if (nextCodeIs("USEPCG")) {
1333+ err=usepcg_statement();
1334+ } else if (nextCodeIs("SCROLL ")) {
1335+ err=scroll_statement();
1336+ } else if (nextCodeIs("WAIT ")) {
1337+ err=wait_statement();
1338+ } else if (nextCodeIs("USEGRAPHIC")) {
1339+ err=usegraphic_statement();
1340+ } else if (nextCodeIs("PSET ")) {
1341+ err=graphic_statement(FUNC_PSET);
1342+ } else if (nextCodeIs("LINE ")) {
1343+ err=graphic_statement(FUNC_LINE);
1344+ } else if (nextCodeIs("BOXFILL ")) {
1345+ err=graphic_statement(FUNC_BOXFILL);
1346+ } else if (nextCodeIs("CIRCLE ")) {
1347+ err=graphic_statement(FUNC_CIRCLE);
1348+ } else if (nextCodeIs("CIRCLEFILL ")) {
1349+ err=graphic_statement(FUNC_CIRCLEFILL);
1350+ } else if (nextCodeIs("GPRINT ")) {
1351+ err=graphic_statement(FUNC_GPRINT);
1352+ } else if (nextCodeIs("PUTBMP ")) {
1353+ err=graphic_statement(FUNC_PUTBMP);
1354+ } else if (nextCodeIs("POINT ")) {
1355+ err=graphic_statement(FUNC_POINT);
1356+ } else if (nextCodeIs("VAR ")) {
1357+ err=var_statement();
1358+ } else if (nextCodeIs("DO")) {
1359+ err=do_statement();
1360+ } else if (nextCodeIs("LOOP")) {
1361+ err=loop_statement();
1362+ } else if (nextCodeIs("WHILE ")) {
1363+ err=while_statement();
1364+ } else if (nextCodeIs("WEND")) {
1365+ err=wend_statement();
1366+ } else if (nextCodeIs("BREAK")) {
1367+ err=break_statement();
1368+ } else if (nextCodeIs("SYSTEM")) {
1369+ err=system_statement();
1370+#ifdef __DEBUG
1371+ } else if (nextCodeIs("DEBUG")) {
1372+ err=debug_statement();
1373+#endif
1374+ } else {
1375+ err=let_statement();
1376+ }
1377+ if (err) return err;
1378+ // Stack handler must be zero here.
1379+ if (g_sdepth!=0) return ERR_UNKNOWN;
1380+ // Check if temp area is used
1381+ if (g_temp_area_used) {
1382+ // Temp area is used. Insert a garbage collection flag setting routine.
1383+ check_obj_space(1);
1384+ g_object[g_objpos++]=0x7ED6F000;// ext s6,s6,0,31
1385+ }
1386+ return 0;
1387+}
--- mips/tags/zoea1.00/linker.c (nonexistent)
+++ mips/tags/zoea1.00/linker.c (revision 148)
@@ -0,0 +1,368 @@
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+unsigned int g_label;
11+
12+char* get_label(void){
13+ unsigned int i;
14+ char b1;
15+ int prevpos;
16+ next_position();
17+ prevpos=g_srcpos;
18+ i=0;
19+ b1=g_source[g_srcpos];
20+ if ('0'<= b1 && b1<='9') {
21+ // May be line number
22+ do {
23+ i*=10;
24+ i+=b1-'0';
25+ g_srcpos++;
26+ b1=g_source[g_srcpos];
27+ } while ('0'<= b1 && b1<='9');
28+ // Check if end of the statement.
29+ if (i==0 || 65535<i) {
30+ // Line number 0 or more than 65535 is not available
31+ g_srcpos=prevpos;
32+ return ERR_SYNTAX;
33+ } else if (get_operator()) {
34+ // Oparator not found.
35+ g_label=i;
36+ return 0;
37+ } else {
38+ // This is not constant line number.
39+ g_srcpos=prevpos;
40+ g_label=0;
41+ return 0;
42+ }
43+ } else if ('A'<=b1 && b1<='Z') {
44+ // May be label
45+ do {
46+ // First character must be A-Z
47+ // From second, A-Z and 0-9 can be used.
48+ i*=36;
49+ if ('0'<=b1 && b1<='9') {
50+ i+=b1-'0';
51+ } else if (g_srcpos==prevpos) {
52+ // First character must be A-Z.
53+ // Subtract 9, resulting 1-26 but not 10-35.
54+ // This subtraction is required to maintain
55+ // final number being <0x80000000.
56+ i+=b1-'A'+1;
57+ } else {
58+ i+=b1-'A'+10;
59+ }
60+ g_srcpos++;
61+ b1=g_source[g_srcpos];
62+ } while ('0'<= b1 && b1<='9' || 'A'<=b1 && b1<='Z');
63+ // Length of the label must be between 2 and 6.
64+ if (g_srcpos-prevpos<2 || 6<g_srcpos-prevpos) {
65+ g_srcpos=prevpos;
66+ return ERR_LABEL_LONG;
67+ }
68+ // Must not be a function
69+ next_position();
70+ if (g_source[g_srcpos]=='(') {
71+ g_srcpos=prevpos;
72+ g_label=0;
73+ return 0;
74+ }
75+ g_label=i+65536;
76+ return 0;
77+ } else {
78+ g_label=0;
79+ return 0;
80+ }
81+}
82+
83+void* search_label(unsigned int label){
84+ unsigned int i,code,search1,search2;
85+ if (label&0xFFFF0000) {
86+ // Label
87+ search1=0x3C160000|((label>>16)&0x0000FFFF); //lui s6,yyyy;
88+ search2=0x36D60000|(label&0x0000FFFF); //ori s6,s6,zzzz;
89+ for(i=0;i<g_objpos;i++){
90+ code=g_object[i];
91+ if (code==search1) {
92+ if (g_object[i+1]==search2) {
93+ // Label number found
94+ return &(g_object[i]);
95+ }
96+ }
97+ if (code&0xFFFF0000==0x04110000) {
98+ // "bgezal zero," assembly found. Skip following block (strig).
99+ i+=code&0x0000FFFF;
100+ i--;
101+ }
102+ }
103+ // Line number not found.
104+ return 0;
105+ } else {
106+ // Line number
107+ search1=0x34160000|label; //ori s6,zero,xxxx;
108+ for(i=0;i<g_objpos;i++){
109+ code=g_object[i];
110+ if (code==search1) {
111+ // Line number found
112+ return &(g_object[i]);
113+ }
114+ if (code&0xFFFF0000==0x04110000) {
115+ // "bgezal zero," assembly found. Skip following block (strig).
116+ i+=code&0x0000FFFF;
117+ i--;
118+ }
119+ }
120+ // Line number not found.
121+ return 0;
122+ }
123+}
124+
125+void* search_breakout(unsigned int start){
126+ unsigned int pos,code1,depth;
127+ // Start search from start point where BREAK statement is used.
128+ depth=0;
129+ for(pos=start;pos<g_objpos;pos++){
130+ code1=g_object[pos];
131+ switch(code1>>16){
132+ case 0x0411:
133+ // "bgezal zero," assembly found. Skip following block (strig).
134+ pos+=code1&0x0000FFFF;
135+ pos--;
136+ break;
137+ case 0x0820: // FOR
138+ case 0x0821: // WHILE
139+ case 0x0822: // DO
140+ depth++;
141+ break;
142+ case 0x0830: // NEXT
143+ case 0x0831: // WEND
144+ case 0x0832: // LOOP
145+ if (0<depth) {
146+ depth--;
147+ break;
148+ }
149+ // Destination found.
150+ return (void*)&g_object[pos];
151+ default:
152+ break;
153+ }
154+ }
155+ return 0;
156+}
157+
158+void* search_ifout(unsigned int start){
159+ unsigned int pos,code1,depth;
160+ // Start search from start point where BREAK statement is used.
161+ depth=0;
162+ for(pos=start;pos<g_objpos;pos++){
163+ code1=g_object[pos];
164+ switch(code1>>16){
165+ case 0x0411:
166+ // "bgezal zero," assembly found. Skip following block (strig).
167+ pos+=code1&0x0000FFFF;
168+ pos--;
169+ break;
170+ case 0x3000: // Block marker
171+ if (code1&0x00008000) {
172+ // end block
173+ if (0<depth) {
174+ depth--;
175+ break;
176+ }
177+ // Destination found.
178+ return (void*)&g_object[pos];
179+ } else {
180+ // begin block
181+ depth++;
182+ }
183+ default:
184+ break;
185+ }
186+ }
187+ return 0;
188+}
189+
190+/*
191+ Following codes are dedicated to specific use:
192+ 0x0810xxxx, 0x0811xxxx: GOTO statement
193+ 0x0812xxxx, 0x0813xxxx: GOSUB statement
194+ 0x0814xxxx, 0x0815xxxx: SOUND etc, for setting v0 as pointer to DATA array.
195+ 0x0816xxxx: BREAK statemant and relatives
196+ 0x08160000: BREAK
197+ 0x08160100: Jump to next ELSE, ELSEIF or ENDIF
198+ 0x082xyyyy: Begin block (FOR/DO/WHILE)
199+ 0x083xyyyy: End block (NEXT/LOOP/WEND)
200+ 0x00000020, 0x00000021,
201+ 0x00000022, 0x00000023: Marker for begining the DATA region.
202+ MLB 2 bits show skip byte length in DATA.
203+ 0x30000000: Begin block (IF-THEN-ELSEIF-ELSE-ENDIF)
204+ 0x30008000: End block (IF-THEN-ELSEIF-ELSE-ENDIF)
205+
206+ IF-THEN-ELSEIF-ELSE-ENDIF is written as follows:
207+ IF-THEN: 0x30000000 0x10400000 0x30000000
208+ ELSEIF-THEN: 0x08160100 0x30008000 (conditional expression) 0x10400000 0x30000000
209+ ELSE: 0x08160100 0x30008000 0x30000000
210+ ENDIF: 0x30008000 0x30008000
211+ , where "0x10400000 0x30000000" and "0x08160100 0x30008000" will be replaced by
212+ codes jumping to next 0x30008000. The 0x30000000 - 0x30008000 blocks will be skipped.
213+*/
214+
215+char* link(void){
216+ int pos;
217+ unsigned int code1,code2,label;
218+ g_fileline=0;
219+ for(pos=0;pos<g_objpos;pos++){
220+ code1=g_object[pos];
221+ switch(code1>>16){
222+ case 0x0411:
223+ // "bgezal zero," assembly found. Skip following block (strig).
224+ pos+=code1&0x0000FFFF;
225+ pos--;
226+ break;
227+ case 0x3416:
228+ // "ori s6,zero,xxxx" found this is the first word in a line.
229+ g_fileline++;
230+ g_line=code1&0x0000FFFF;
231+ break;
232+ case 0x0810:
233+ // GOTO
234+ code2=g_object[pos+1];
235+ if ((code2&0xFFFF0000)!=0x08110000) continue;
236+ code1&=0x0000FFFF;
237+ code2&=0x0000FFFF;
238+ label=(code1<<16)|code2;
239+ code1=(int)search_label(label);
240+ g_label=label;
241+ if (!code1) return ERR_LABEL_NF;
242+ code1&=0x0FFFFFFF;
243+ code1>>=2;
244+ code1|=0x08000000; // j xxxx
245+ g_object[pos++]=code1;
246+ g_object[pos]=0x00000000; // nop
247+ break;
248+ case 0x0812:
249+ // GOSUB
250+ code2=g_object[pos+1];
251+ if ((code2&0xFFFF0000)!=0x08130000) continue;
252+ code1&=0x0000FFFF;
253+ code2&=0x0000FFFF;
254+ label=(code1<<16)|code2;
255+ code2=(int)search_label(label);
256+ g_label=label;
257+ if (!code2) return ERR_LABEL_NF;
258+ code2&=0x0FFFFFFF;
259+ code2>>=2;
260+ code2|=0x08000000; // j xxxx
261+ g_object[pos++]=0x00000000; // nop
262+ g_object[pos]=code2;
263+ break;
264+ case 0x0814:
265+ // SOUND etc, for setting v0 as pointer to label/line
266+ code2=g_object[pos+1];
267+ if ((code2&0xFFFF0000)!=0x08150000) continue;
268+ code1&=0x0000FFFF;
269+ code2&=0x0000FFFF;
270+ label=(code1<<16)|code2;
271+ code1=(int)search_label(label);
272+ g_label=label;
273+ if (!code1) return ERR_LABEL_NF;
274+ g_object[pos++]=0x3C020000|((code1>>16)&0x0000FFFF); // lui v0,xxxx
275+ g_object[pos] =0x34420000|(code1&0x0000FFFF); // ori v0,v0,xxxx
276+ break;
277+ case 0x0816:
278+ switch(code1&0xFFFF) {
279+ case 0x0000:
280+ // BREAK statement
281+ // Find next the NEXT or WHILE statement and insert jump code after this.
282+ g_label=g_line;
283+ code1=(int)search_breakout(pos);
284+ if (!code1) return ERR_INVALID_BREAK;
285+ code1&=0x0FFFFFFF;
286+ code1>>=2;
287+ code1|=0x08000000; // j xxxx
288+ g_object[pos]=code1;
289+ break;
290+ case 0x0100:
291+ // Jump to next ENDIF
292+ g_label=g_line;
293+ // "pos+2" is for skipping next code (must be 0x30008000)
294+ code1=(int)search_ifout(pos+2);
295+ if (!code1) return ERR_INVALID_ELSEIF;
296+ code1&=0x0FFFFFFF;
297+ code1>>=2;
298+ code1|=0x08000000; // j xxxx
299+ g_object[pos]=code1;
300+ break;
301+ default:
302+ break;
303+ }
304+ break;
305+ case 0x3000:
306+ // Block marker
307+ switch(code1&0xFFFF) {
308+ case 0x0000:
309+ // Begin if block
310+ if (g_object[pos-1]==0x10400000) { // beq v0,zero,xxxx
311+ // IF-THEN or ELSEIF-THEN
312+ // Jump to next ELSE, ELSEIF or ENDIF
313+ g_label=g_line;
314+ // "pos+1" is for skipping current code (0x30000000)
315+ code1=(int)search_ifout(pos+1);
316+ if (!code1) return ERR_INVALID_ELSEIF;
317+ code1-=(int)(&g_object[pos]);
318+ code1>>=2;
319+ code1&=0x0000FFFF;
320+ code1|=0x10400000; // beq v0,zero,xxxx
321+ g_object[pos-1]=code1;
322+ break;
323+ }
324+ break;
325+ default:
326+ break;
327+ }
328+ break;
329+ case 0x0820: // FOR
330+ case 0x0830: // NEXT
331+ case 0x0821: // WHILE
332+ case 0x0831: // WEND
333+ case 0x0822: // DO
334+ case 0x0832: // WHILE
335+ // These are used for detecing the depth of structures.
336+ // Change them to stack increase/decrease commands.
337+ g_object[pos]=0x27BD0000|(code1&0x0000FFFF); //// addiu sp,sp,xx
338+ break;
339+ case 0x2407: // addiu a3,zero,xxxx
340+ if (g_object[pos-1]!=0x02E0F809) break; // jalr ra,s7
341+ // call_lib_code(x)
342+ switch(code1&0x0000FFFF){
343+ case LIB_RESTORE:
344+ // Convert label data to pointer if not dynamic
345+ code1=g_object[pos-3];
346+ code2=g_object[pos-2];
347+ if ((code1>>16)!=0x3C02) break; // lui v0,xxxx
348+ if ((code2>>16)!=0x3442) break; // ori v0,v0,xxxx
349+ label=(code1<<16)|(code2&0x0000FFFF);
350+ code1=(int)search_label(label);
351+ g_label=label;
352+ if (!code1) return ERR_LABEL_NF;
353+ code2=code1&0x0000FFFF;
354+ code1=code1>>16;
355+ g_object[pos-3]=0x3C020000|code1; // lui v0,xxxx
356+ g_object[pos-2]=0x34420000|code2; // ori v0,v0,xxxx
357+ g_object[pos]=0x24070000|LIB_RESTORE2; // addiu a3,zero,xxxx
358+ break;
359+ default:
360+ break;
361+ }
362+ break;
363+ default:
364+ break;
365+ }
366+ }
367+ return 0;
368+}
\ No newline at end of file
--- mips/tags/zoea1.00/float.c (nonexistent)
+++ mips/tags/zoea1.00/float.c (revision 148)
@@ -0,0 +1,150 @@
1+#include "./compiler.h"
2+#include "stdlib.h"
3+
4+char* get_float_sub(int pr);
5+
6+char* get_simple_float(void){
7+ int i;
8+ float f;
9+ char* err;
10+ char b1,b2,b3;
11+ next_position();
12+ b1=g_source[g_srcpos];
13+ if (b1=='(') {
14+ // (...)
15+ // Parenthesis
16+ g_srcpos++;
17+ next_position();
18+ err=get_float_sub(priority(OP_VOID));
19+ if (err) return err;
20+ next_position();
21+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
22+ g_srcpos++;
23+ } else if (b1=='-') {
24+ // Unary '-' operator
25+ // Note that unary operators ( + and - ) have higher priority than the other operators
26+ g_srcpos++;
27+ err=get_simple_float();
28+ if (err) return err;
29+ check_obj_space(2);
30+ g_object[g_objpos++]=0x3404; // ori a0,zero,0x123
31+ g_object[g_objpos++]=0x34050000|(OP_SUB&0x0000FFFF); // ori a1,zero,xxxx
32+ call_lib_code(LIB_FLOAT);
33+ } else {
34+ // Main routine of getting float value here
35+ if (b1=='+') g_srcpos++; // Ignore unary '+' operator
36+ next_position();
37+ b1=g_source[g_srcpos];
38+ b2=g_source[g_srcpos+1];
39+ b3=g_source[g_srcpos+2];
40+ if ('0'<=b1 && b1<='9') {
41+ f=strtof((const char*)&g_source[g_srcpos],&err);
42+ if (&g_source[g_srcpos]==err) return ERR_SYNTAX;
43+ g_srcpos=err-g_source;
44+ i=((int*)(&f))[0];
45+ if (i&0xFFFF0000) {
46+ // 32 bit
47+ check_obj_space(2);
48+ g_object[g_objpos++]=0x3C020000|((i>>16)&0x0000FFFF); // lui v0,xxxx
49+ g_object[g_objpos++]=0x34420000|(i&0x0000FFFF); // ori v0,v0,xxxx
50+ } else {
51+ // 16 bit
52+ check_obj_space(1);
53+ g_object[g_objpos++]=0x34020000|(i&0x0000FFFF); // ori v0,zero,xxxx
54+ }
55+ } else {
56+ if ('A'<=b1 && b1<='Z' && b2=='#' && b3=='(') {
57+ // A( - Z(
58+ // Dimension
59+ g_srcpos++;
60+ g_srcpos++;
61+ g_srcpos++;
62+ return get_dim_value(b1);
63+ } else if ('A'<=b1 && b1<='Z' && b2=='#') {
64+ // A-Z
65+ // Simple value
66+ g_srcpos++;
67+ g_srcpos++;
68+ check_obj_space(1);
69+ g_object[g_objpos++]=0x8FC20000|((b1-'A')*4); // lw v0,xx(s8)
70+ } else if ('A'<=b1 && b1<='Z') {
71+ // Starts with A-Z
72+ // Functions
73+ return float_function();
74+ } else {
75+ return ERR_SYNTAX;
76+ }
77+ }
78+ }
79+ // No error
80+ return 0;
81+}
82+
83+char* get_float_sub(int pr){
84+ char* err;
85+ enum operator op;
86+ char b1,b2,b3;
87+ int prevpos;
88+ // Get a value in $v0.
89+ err=get_simple_float();
90+ if (err) return err;
91+ while(1){
92+ // Get the operator in op. If not valid operator, simply return without error.
93+ prevpos=g_srcpos;
94+ err=get_floatOperator();
95+ if (err) return 0;
96+ op=g_last_op;
97+ // Compair current and previous operators.
98+ // If the previous operator has higher priolity, return.
99+ if (pr>=priority(op)) {
100+ g_srcpos=prevpos;
101+ return 0;
102+ }
103+ // Store $v0 in stack
104+ g_sdepth+=4;
105+ if (g_maxsdepth<g_sdepth) g_maxsdepth=g_sdepth;
106+ check_obj_space(1);
107+ g_object[g_objpos++]=0xAFA20000|g_sdepth; // sw v0,xx(sp)
108+ // Get next value.
109+ err=get_float_sub(priority(op));
110+ if (err) return err;
111+ // Get value from stack to $a0.
112+ check_obj_space(1);
113+ g_object[g_objpos++]=0x8FA40000|g_sdepth; // lw a0,xx(sp)
114+ g_sdepth-=4;
115+ // Calculation. Result will be in $v0.
116+ err=calculation_float(op);
117+ if (err) return err;
118+ }
119+}
120+
121+char* get_float(){
122+ // Note that this can be called recursively.
123+ // Value may contain function with a parameter of another value.
124+ char* err;
125+ int prevpos;
126+ if (g_sdepth==0) {
127+ // Initialize stack handler
128+ g_maxsdepth=0;
129+ prevpos=g_objpos;
130+ // Stack decrement command will be filled later
131+ check_obj_space(1);
132+ g_objpos++;
133+ }
134+ err=get_float_sub(priority(OP_VOID));
135+ if (err) return err;
136+ if (g_sdepth==0) {
137+ if (g_maxsdepth==0) {
138+ // Stack was not used.
139+ shift_obj(&g_object[prevpos+1],&g_object[prevpos],g_objpos-prevpos-1);
140+ g_objpos--;
141+ } else {
142+ // Stack was used.
143+ check_obj_space(1);
144+ g_object[prevpos]=0x27BD0000 | (0-g_maxsdepth) & 0x0000FFFF; // addiu sp,sp,-xx
145+ g_object[g_objpos++]=0x27BD0000 | g_maxsdepth & 0x0000FFFF; // addiu sp,sp,xx
146+ }
147+ }
148+ g_lastvar=VAR_FLOAT;
149+ return 0;
150+}
\ No newline at end of file
--- mips/tags/zoea1.00/videoout.h (nonexistent)
+++ mips/tags/zoea1.00/videoout.h (revision 148)
@@ -0,0 +1,108 @@
1+#define WIDTH_X 30 // 横方向文字数
2+#define WIDTH_Y 27 // 縦方向文字数
3+#define ATTROFFSET (WIDTH_X*WIDTH_Y) // VRAM上のカラーパレット格納位置
4+
5+#define G_X_RES 256 // 横方向解像度
6+#define G_Y_RES 224 // 縦方向解像度
7+#define G_H_WORD (G_X_RES/4) // 1行当りのワード数(16bit単位)
8+
9+
10+// 入力ボタンのポート、ビット定義
11+#define KEYPORT PORTB
12+#define KEYUP 0x0400
13+#define KEYDOWN 0x0080
14+#define KEYLEFT 0x0100
15+#define KEYRIGHT 0x0200
16+#define KEYSTART 0x0800
17+#define KEYFIRE 0x4000
18+
19+extern volatile char drawing; // 表示期間中は-1
20+extern volatile unsigned short drawcount; // 1画面表示終了ごとに1足す。アプリ側で0にする。
21+ // 最低1回は画面表示したことのチェックと、アプリの処理が何画面期間必要かの確認に利用。
22+extern unsigned char TVRAM[]; //テキストビデオメモリ
23+extern unsigned short *gVRAM; //グラフィックVRAM開始位置のポインタ
24+
25+extern const unsigned char FontData[]; //フォントパターン定義
26+extern unsigned char *cursor;
27+extern unsigned char cursorcolor;
28+extern unsigned char *fontp;
29+
30+void start_composite(void); //カラーコンポジット出力開始
31+void stop_composite(void); //カラーコンポジット出力停止
32+void init_composite(void); //カラーコンポジット出力初期化
33+void clearscreen(void); //テキスト画面クリア
34+void set_palette(unsigned char n,unsigned char b,unsigned char r,unsigned char g); //テキストパレット設定
35+void set_bgcolor(unsigned char b,unsigned char r,unsigned char g); //バックグランドカラー設定
36+void set_graphmode(unsigned char m); //グラフィックモード変更
37+void init_graphic(unsigned short *gvram); //グラフィック機能利用準備
38+
39+void vramscroll(void);
40+ //1行スクロール
41+void setcursor(unsigned char x,unsigned char y,unsigned char c);
42+ //カーソル位置とカラーを設定
43+void setcursorcolor(unsigned char c);
44+ //カーソル位置そのままでカラー番号をcに設定
45+void printchar(unsigned char n);
46+ //カーソル位置にテキストコードnを1文字表示し、カーソルを1文字進める
47+void printstr(unsigned char *s);
48+ //カーソル位置に文字列sを表示
49+void printnum(unsigned int n);
50+ //カーソル位置に符号なし整数nを10進数表示
51+void printnum2(unsigned int n,unsigned char e);
52+ //カーソル位置に符号なし整数nをe桁の10進数表示(前の空き桁部分はスペースで埋める)
53+void cls(void);
54+ //テキスト画面消去し、カーソルを先頭に移動
55+void startPCG(unsigned char *p,int a);
56+ // RAMフォント(PCG)の利用開始、pがフォント格納場所、aが0以外でシステムフォントをコピー
57+void stopPCG(void);
58+ // RAMフォント(PCG)の利用停止
59+
60+void g_clearscreen(void);
61+//グラフィック画面クリア
62+void g_set_palette(unsigned char n,unsigned char b,unsigned char r,unsigned char g);
63+//グラフィック用カラーパレット設定
64+
65+void g_pset(int x,int y,unsigned int c);
66+// (x,y)の位置にカラーcで点を描画
67+
68+void g_putbmpmn(int x,int y,char m,char n,const unsigned char bmp[]);
69+// 横m*縦nドットのキャラクターを座標x,yに表示
70+// unsigned char bmp[m*n]配列に、単純にカラー番号を並べる
71+// カラー番号が0の部分は透明色として扱う
72+
73+void g_clrbmpmn(int x,int y,char m,char n);
74+// 縦m*横nドットのキャラクター消去
75+// カラー0で塗りつぶし
76+
77+void g_gline(int x1,int y1,int x2,int y2,unsigned int c);
78+// (x1,y1)-(x2,y2)にカラーcで線分を描画
79+
80+void g_hline(int x1,int x2,int y,unsigned int c);
81+// (x1,y)-(x2,y)への水平ラインを高速描画
82+
83+void g_circle(int x0,int y0,unsigned int r,unsigned int c);
84+// (x0,y0)を中心に、半径r、カラーcの円を描画
85+
86+void g_boxfill(int x1,int y1,int x2,int y2,unsigned int c);
87+// (x1,y1),(x2,y2)を対角線とするカラーcで塗られた長方形を描画
88+
89+void g_circlefill(int x0,int y0,unsigned int r,unsigned int c);
90+// (x0,y0)を中心に、半径r、カラーcで塗られた円を描画
91+
92+void g_putfont(int x,int y,unsigned int c,int bc,unsigned char n);
93+//8*8ドットのアルファベットフォント表示
94+//座標(x,y)、カラー番号c
95+//bc:バックグランドカラー、負数の場合無視
96+//n:文字番号
97+
98+void g_printstr(int x,int y,unsigned int c,int bc,unsigned char *s);
99+//座標(x,y)からカラー番号cで文字列sを表示、bc:バックグランドカラー
100+
101+void g_printnum(int x,int y,unsigned char c,int bc,unsigned int n);
102+//座標(x,y)にカラー番号cで数値nを表示、bc:バックグランドカラー
103+
104+void g_printnum2(int x,int y,unsigned char c,int bc,unsigned int n,unsigned char e);
105+//座標(x,y)にカラー番号cで数値nを表示、bc:バックグランドカラー、e桁で表示
106+
107+unsigned int g_color(int x,int y);
108+//座標(x,y)のVRAM上の現在のパレット番号を返す、画面外は0を返す
--- mips/tags/zoea1.00/error.c (nonexistent)
+++ mips/tags/zoea1.00/error.c (revision 148)
@@ -0,0 +1,143 @@
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+};
30+
31+char* resolve_label(int s6){
32+ static char str[7];
33+ int i,j;
34+ if (s6<65536) {
35+ // Line number
36+ for(i=0;i<5;i++){
37+ str[5-i]='0'+rem10_32(s6);
38+ s6=div10_32(s6);
39+ }
40+ str[6]=0x00;
41+ for(j=1;j<5;j++){
42+ if (str[j]!='0') break;
43+ }
44+ return (char*)(str+j);
45+ } else {
46+ // Label
47+ s6-=65536;
48+ str[6]=0x00;
49+ for(i=5;0<=i;i--){
50+ if (s6<36) {
51+ // First character must be A-Z, corresponding to 1-26 but not 10-35.
52+ // See get_label() for the detail.
53+ str[i]=s6-1+'A';
54+ break;
55+ } else {
56+ // From second, 0-9 corresponds to 0-9 and A-Z corresponds to 10-35.
57+ str[i]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[rem36_32(s6)];
58+ s6=div36_32(s6);
59+ }
60+ }
61+ return (char*)(str+i);
62+ }
63+}
64+
65+void pre_end_addr(int s6){
66+ int i,j;
67+ char str[7];
68+ if (s6<0) s6=s6&0x7fffffff;
69+ g_label=s6;
70+ if (s6<65536) {
71+ // Line number
72+ printstr("\nIn line ");
73+ } else {
74+ // Label
75+ printstr("\nAfter label ");
76+ }
77+ printstr(resolve_label(s6));
78+ asm volatile("la $v0,%0"::"i"(&g_end_addr));
79+ asm volatile("lw $v0,0($v0)");
80+ asm volatile("nop");
81+ asm volatile("jr $v0");
82+}
83+
84+#define end_exec() \
85+ asm volatile("addu $a0,$s6,$zero");\
86+ asm volatile("j pre_end_addr")
87+
88+void err_break(void){
89+ printstr(ERR_BREAK);
90+ end_exec();
91+}
92+
93+void err_data_not_found(void){
94+ printstr(ERR_DATA_NF);
95+ end_exec();
96+}
97+
98+void err_label_not_found(void){
99+ printstr(ERR_LABEL_NF);
100+ printstr(resolve_label(g_label));
101+ printstr("\n");
102+ end_exec();
103+}
104+
105+void err_div_zero(void){
106+ printstr(ERR_DIV_0);
107+ end_exec();
108+}
109+
110+void err_no_mem(void){
111+ printstr(ERR_NE_MEMORY);
112+ end_exec();
113+}
114+
115+void err_str_complex(void){
116+ printstr(ERR_STR_COMPLEX);
117+ end_exec();
118+}
119+
120+void err_unknown(void){
121+ printstr(ERR_UNKNOWN);
122+ end_exec();
123+}
124+
125+void err_music(char* str){
126+ printstr(ERR_MUSIC);
127+ printstr(str);
128+ printstr("'\n");
129+ // Restore s6 from g_s6
130+ asm volatile("la $s6,%0"::"i"(&g_s6));
131+ asm volatile("lw $s6,0($s6)");
132+ end_exec();
133+}
134+
135+void err_unexp_next(void){
136+ printstr(ERR_UNEXP_NEXT);
137+ end_exec();
138+}
139+
140+void err_no_block(void){
141+ printstr(ERR_NO_BLOCK);
142+ end_exec();
143+}
--- mips/tags/zoea1.00/globalvars.c (nonexistent)
+++ mips/tags/zoea1.00/globalvars.c (revision 148)
@@ -0,0 +1,71 @@
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 "compiler.h"
9+#include "main.h"
10+
11+// Contain the valus of $gp and $s6 (GPR of MIPS32)
12+int g_gp;
13+int g_s6;
14+
15+// Line data when compiling
16+int g_line;
17+int g_fileline;
18+
19+// Contain the address to which return in "END" statement.
20+int g_end_addr;
21+
22+// Following vars are used in value.c and string.c.
23+// These define the depth of stack pointer used for
24+// handling values and strings.
25+int g_sdepth;
26+int g_maxsdepth;
27+
28+// Following var shows what type of variable was defined
29+// in compiling the last code.
30+enum variable g_lastvar;
31+
32+// Vars used for handling constant integer
33+int g_intconst;
34+char g_valueisconst;
35+
36+// Global vars associated to RAM
37+char* g_source;
38+int g_srcpos;
39+int* g_object;
40+int g_objpos;
41+int* g_objmax;
42+char RAM[RAMSIZE] __attribute__((persistent,address(0xA0000000+PIC32MX_RAMSIZE-PERSISTENT_RAM_SIZE)));
43+unsigned int g_ex_data[EXCEPTION_DATA_SIZE/4] __attribute__((persistent,address(0xA0000000+PIC32MX_RAMSIZE-EXCEPTION_DATA_SIZE)));
44+
45+// Global area for vars A-Z and three temporary string pointers
46+int g_var_mem[ALLOC_BLOCK_NUM];
47+unsigned short g_var_pointer[ALLOC_BLOCK_NUM];
48+unsigned short g_var_size[ALLOC_BLOCK_NUM];
49+
50+// Flag to use temporary area when compiling
51+char g_temp_area_used;
52+
53+// Heap area
54+int* g_heap_mem;
55+int g_max_mem;
56+
57+// Random seed
58+int g_rnd_seed;
59+
60+// Enable/disable Break keys
61+char g_disable_break;
62+
63+// Font data used for PCG
64+unsigned char* g_pcg_font;
65+
66+// Use or do not use graphic
67+char g_use_graphic;
68+
69+// Pointer to graphic RAM
70+unsigned short* g_graphic_area;
71+
--- mips/tags/zoea1.00/value.c (nonexistent)
+++ mips/tags/zoea1.00/value.c (revision 148)
@@ -0,0 +1,271 @@
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+ Public function is only get_value().
10+*/
11+
12+#include "compiler.h"
13+
14+char* get_value();
15+char* get_value_sub(int pr);
16+
17+char* get_dim_value(char b1){
18+ char* err;
19+ err=get_value_sub(priority(OP_VOID));
20+ if (err) return err;
21+ check_obj_space(4);
22+ g_object[g_objpos++]=0x00021080; // sll v0,v0,0x2
23+ g_object[g_objpos++]=0x8FC30000|((b1-'A')*4); // lw v1,xx(s8)
24+ g_object[g_objpos++]=0x00621821; // addu v1,v1,v0
25+ g_object[g_objpos++]=0x8C620000; // lw v0,0(v1)
26+ next_position();
27+ if (g_source[g_srcpos]==','){
28+ // 2D, 3D or more
29+ check_obj_space(2);
30+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
31+ do {
32+ g_srcpos++;
33+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
34+ err=get_value_sub(priority(OP_VOID));
35+ if (err) return err;
36+ check_obj_space(5);
37+ g_object[g_objpos++]=0x00021080; // sll v0,v0,0x2
38+ g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp)
39+ g_object[g_objpos++]=0x00621821; // addu v1,v1,v0
40+ g_object[g_objpos++]=0x8C620000; // lw v0,0(v1)
41+ } while (g_source[g_srcpos]==',');
42+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
43+ }
44+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
45+ g_srcpos++;
46+ return 0;
47+}
48+
49+char* get_simple_value(void){
50+ int i;
51+ char* err;
52+ char b1,b2;
53+ next_position();
54+ b1=g_source[g_srcpos];
55+ if (b1=='(') {
56+ // (...)
57+ // Parenthesis
58+ g_srcpos++;
59+ next_position();
60+ err=get_value_sub(priority(OP_VOID));
61+ if (err) return err;
62+ next_position();
63+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
64+ g_srcpos++;
65+ } else if (b1=='-') {
66+ // Unary '-' operator
67+ // Note that unary operators ( + and - ) have higher priority than the other operators
68+ g_srcpos++;
69+ err=get_simple_value();
70+ if (err) return err;
71+ check_obj_space(1);
72+ g_object[g_objpos++]=0x00021023; // subu v0,zero,v0
73+ g_intconst=-g_intconst;
74+ } else {
75+ // Main routine of getting value here
76+ if (b1=='+') g_srcpos++; // Ignore unary '+' operator
77+ next_position();
78+ b1=g_source[g_srcpos];
79+ b2=g_source[g_srcpos+1];
80+ if (b1=='0' && b2=='X' || b1=='$') {
81+ // Starts with '0x' or '$'
82+ // Hex number
83+ g_srcpos++;
84+ if (b1=='0') g_srcpos++;
85+ i=0;
86+ while(b1=g_source[g_srcpos]) {
87+ if ('0'<=b1 && b1<='9') {
88+ i*=16;
89+ i+=b1-'0';
90+ } else if ('A'<=b1 && b1<='F') {
91+ i*=16;
92+ i+=b1-'A'+0x0A;
93+ } else {
94+ break;
95+ }
96+ g_srcpos++;
97+ }
98+ g_intconst=i;
99+ if (i&0xFFFF0000) {
100+ // 32 bit
101+ check_obj_space(2);
102+ g_object[g_objpos++]=0x3C020000|((i>>16)&0x0000FFFF); // lui v0,xxxx
103+ g_object[g_objpos++]=0x34420000|(i&0x0000FFFF); // ori v0,v0,xxxx
104+ } else {
105+ // 16 bit
106+ check_obj_space(1);
107+ g_object[g_objpos++]=0x34020000|(i&0x0000FFFF); // ori v0,zero,xxxx
108+ }
109+ } else if ('0'<=b1 && b1<='9') {
110+ // Starts with 0-9
111+ // Decimal number
112+ i=0;
113+ while(b1=g_source[g_srcpos]) {
114+ if ('0'<=b1 && b1<='9') {
115+ i*=10;
116+ i+=b1-'0';
117+ } else {
118+ break;
119+ }
120+ g_srcpos++;
121+ }
122+ // The next character should not be '.' or 'E'.
123+ // Or, it must be recognized as a float value.
124+ if (b1=='.' || b1=='E') return ERR_SYNTAX;
125+ g_intconst=i;
126+ if (i&0xFFFF0000) {
127+ // 32 bit
128+ check_obj_space(2);
129+ g_object[g_objpos++]=0x3C020000|((i>>16)&0x0000FFFF); // lui v0,xxxx
130+ g_object[g_objpos++]=0x34420000|(i&0x0000FFFF); // ori v0,v0,xxxx
131+ } else {
132+ // 16 bit
133+ check_obj_space(1);
134+ g_object[g_objpos++]=0x34020000|(i&0x0000FFFF); // ori v0,zero,xxxx
135+ }
136+ } else {
137+ g_valueisconst=0;
138+ if ('A'<=b1 && b1<='Z' && b2=='(') {
139+ // A( - Z(
140+ // Dimension
141+ g_srcpos++;
142+ g_srcpos++;
143+ return get_dim_value(b1);
144+ } else if ('A'<=b1 && b1<='Z' && (b2<'A' || 'Z'<b2) && b2!='#' && b2!='$') {
145+ // A-Z
146+ // Simple value
147+ g_srcpos++;
148+ check_obj_space(1);
149+ g_object[g_objpos++]=0x8FC20000|((b1-'A')*4); // lw v0,xx(s8)
150+ } else if ('A'<=b1 && b1<='Z') {
151+ // Starts with A-Z
152+ // Functions
153+ return function();
154+ } else {
155+ return ERR_SYNTAX;
156+ }
157+ }
158+ }
159+ // No error
160+ return 0;
161+}
162+
163+char* get_value_sub(int pr){
164+ char* err;
165+ enum operator op;
166+ char b1,b2,b3;
167+ int prevpos;
168+ // Get a value in $v0.
169+ err=get_simple_value();
170+ if (err) return err;
171+ while(1){
172+ // Get the operator in op. If not valid operator, simply return without error.
173+ prevpos=g_srcpos;
174+ err=get_operator();
175+ if (err) return 0;
176+ op=g_last_op;
177+ // Compair current and previous operators.
178+ // If the previous operator has higher priolity, return.
179+ if (pr>=priority(op)) {
180+ g_srcpos=prevpos;
181+ return 0;
182+ }
183+ // Store $v0 in stack
184+ g_sdepth+=4;
185+ if (g_maxsdepth<g_sdepth) g_maxsdepth=g_sdepth;
186+ check_obj_space(1);
187+ g_object[g_objpos++]=0xAFA20000|g_sdepth; // sw v0,xx(sp)
188+ // Get next value.
189+ err=get_value_sub(priority(op));
190+ if (err) return err;
191+ // Get value from stack to $v1.
192+ check_obj_space(1);
193+ g_object[g_objpos++]=0x8FA30000|g_sdepth; // lw v1,xx(sp)
194+ g_sdepth-=4;
195+ // Calculation. Result will be in $v0.
196+ err=calculation(op);
197+ if (err) return err;
198+ }
199+}
200+
201+char* get_value(){
202+ // This is only the public function.
203+ // Note that this can be called recursively.
204+ // Value may contain function with a parameter of another value.
205+ char* err;
206+ int prevpos;
207+ if (g_sdepth==0) {
208+ // Initialize stack handler
209+ g_maxsdepth=0;
210+ prevpos=g_objpos;
211+ // Stack decrement command will be filled later
212+ check_obj_space(1);
213+ g_objpos++;
214+ }
215+ err=get_value_sub(priority(OP_VOID));
216+ if (err) return err;
217+ if (g_sdepth==0) {
218+ if (g_maxsdepth==0) {
219+ // Stack was not used.
220+ shift_obj(&g_object[prevpos+1],&g_object[prevpos],g_objpos-prevpos-1);
221+ g_objpos--;
222+ } else {
223+ // Stack was used.
224+ check_obj_space(1);
225+ g_object[prevpos]=0x27BD0000 | (0-g_maxsdepth) & 0x0000FFFF; // addiu sp,sp,-xx
226+ g_object[g_objpos++]=0x27BD0000 | g_maxsdepth & 0x0000FFFF; // addiu sp,sp,xx
227+ }
228+ }
229+ g_lastvar=VAR_INTEGER;
230+ return 0;
231+}
232+
233+char* get_floatOrValue(){
234+ char* err;
235+ char b;
236+ int opos,spos,sdpt;
237+ sdpt=g_sdepth;
238+ opos=g_objpos;
239+ spos=g_srcpos;
240+ // First try integer.
241+ // Integer value has the higher priolity than float value.
242+ err=get_value();
243+ b=g_source[g_srcpos];
244+ if (err) {
245+ // Value is not integer. Let's try float.
246+ g_sdepth=sdpt;
247+ g_objpos=opos;
248+ g_srcpos=spos;
249+ return get_float();
250+ } else {
251+ // Value was recognized as an integer.
252+ return 0;
253+ }
254+}
255+
256+char* get_stringFloatOrValue(){
257+ char* err;
258+ int opos,spos;
259+ opos=g_objpos;
260+ spos=g_srcpos;
261+ // First try string, float, then integer.
262+ err=get_string();
263+ if (err) {
264+ g_objpos=opos;
265+ g_srcpos=spos;
266+ return get_floatOrValue();
267+ } else {
268+ return 0;
269+ }
270+}
271+
--- mips/tags/zoea1.00/exception.c (nonexistent)
+++ mips/tags/zoea1.00/exception.c (revision 148)
@@ -0,0 +1,126 @@
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 "main.h"
11+#include "compiler.h"
12+
13+void _general_exception_handler (void){
14+ int i;
15+ // $v1 is g_ex_data
16+ asm volatile("la $v1,%0"::"i"(&g_ex_data[0]));
17+ // Prepare proper stack area before SoftReset
18+ asm volatile("addiu $sp,$v1,0xfff0");
19+ // g_ex_data[2]=$s6
20+ asm volatile("sw $s6,8($v1)");
21+ // g_ex_data[3]=Cause
22+ asm volatile("mfc0 $v0,$13");
23+ asm volatile("sw $v0,12($v1)");
24+ // g_ex_data[4]=EPC
25+ asm volatile("mfc0 $v0,$14");
26+ asm volatile("sw $v0,16($v1)");
27+ // Exception occured
28+ g_ex_data[0]=1;
29+ // g_s6
30+ g_ex_data[1]=g_s6;
31+ // Clear 2 MLB bits of EPC
32+ g_ex_data[4]&=0xfffffffc;
33+ // If EPC is within RAM, store data in exception area.
34+ if ((int)(&RAM[0])<=g_ex_data[4] && g_ex_data[4] <(int)(&RAM[RAMSIZE])) {
35+ // g_ex_data[5] - g_ex_data[12]: assembly
36+ for(i=-3;i<=3;i++){
37+ g_ex_data[i+8]=((int*)g_ex_data[4])[i];
38+ }
39+ }
40+ // Wait until all buttons are released and reset MachiKania.
41+ #ifdef __DEBUG
42+ asm volatile("j 0xBFC00000");
43+ #else
44+ buttonmode();
45+ for(i=0;i<100000;i++){
46+ if((KEYPORT&(KEYUP|KEYDOWN|KEYLEFT|KEYRIGHT|KEYSTART|KEYFIRE))
47+ !=(KEYUP|KEYDOWN|KEYLEFT|KEYRIGHT|KEYSTART|KEYFIRE)) i=0;
48+ }
49+ asm volatile("j SoftReset");
50+ #endif
51+}
52+
53+void blue_screen(void){
54+ int i,j,s6,s6g;
55+ unsigned int* opos;
56+ if (RCONbits.POR || RCONbits.EXTR) {
57+ // After power on or reset. Reset flags and return.
58+ RCONbits.POR=0;
59+ RCONbits.EXTR=0;
60+ for(i=0;i<RAMSIZE;i++){
61+ // Reset all RAM area including g_ex_data[]
62+ RAM[i]=0;
63+ }
64+ return;
65+ } else if (g_ex_data[0]==0) {
66+ // No exception found.
67+ return;
68+ }
69+ // Exception occured before SoftReset().
70+ // Prepare data
71+ s6=g_ex_data[2];
72+ s6g=g_ex_data[1];
73+ s6=s6&0x7fffffff;
74+ s6g=s6g&0x7fffffff;
75+ opos=(int*)g_ex_data[4];
76+ //set_bgcolor(255,0,0);
77+ printstr("STOP");
78+ printstr("\nException at ");
79+ printhex32(g_ex_data[4]);
80+ printstr("\n Cause: ");
81+ printhex32(g_ex_data[3]);
82+ printstr("\n ");
83+ switch((g_ex_data[3]>>2)&0x1f){
84+ case 0: printstr("(Interrupt)"); break;
85+ case 1: printstr("(TLB modification)"); break;
86+ case 2: printstr("(TLB load/fetch)"); break;
87+ case 3: printstr("(TLB store)"); break;
88+ case 4: printstr("(Address load/fetch error )"); break;
89+ case 5: printstr("(Address store error)"); break;
90+ case 6: printstr("(Bus fetch error)"); break;
91+ case 7: printstr("(Bus load/store error)"); break;
92+ case 8: printstr("(Syscall)"); break;
93+ case 9: printstr("(Breakpoint)"); break;
94+ case 10: printstr("(Reserved instruction)"); break;
95+ case 11: printstr("(Coprocessor Unusable)"); break;
96+ case 12: printstr("(Integer Overflow)"); break;
97+ case 13: printstr("(Trap)"); break;
98+ case 23: printstr("(Reference to Watch address)"); break;
99+ case 24: printstr("(Machine check)"); break;
100+ default: printstr("(Unknown)"); break;
101+ }
102+ printstr("\n s6: ");
103+ printstr(resolve_label(s6));
104+ printstr("\n g_s6: ");
105+ printstr(resolve_label(s6g));
106+ printstr("\n");
107+ printstr("Reset MachiKania to contine.\n\n");
108+ // Show code where the exception happened.
109+ for(i=-3;i<=3;i++){
110+ printstr("\n ");
111+ printhex32((unsigned int)&opos[i]);
112+ printstr(" ");
113+ if ((unsigned int)&RAM[0]<=(unsigned int)&opos[i] && (unsigned int)&opos[i]<(unsigned int)&RAM[RAMSIZE]) {
114+ // Exception in RAM[RAMSIZE] area
115+ printhex32(g_ex_data[i+8]);
116+ } else if ( 0xA0000000<=(unsigned int)&opos[i] && (unsigned int)&opos[i]<0xA0000000+PIC32MX_RAMSIZE
117+ || 0x9D000000<=(unsigned int)&opos[i] && (unsigned int)&opos[i]<=0x9D000000+PIC32MX_FLASHSIZE) {
118+ // Exception in outside RAM[RAMSIZE] or flash area
119+ printhex32(opos[i]);
120+ } else {
121+ printstr("********");
122+ }
123+ }
124+ printstr("\n");
125+ while(1) asm("wait");
126+}
--- mips/tags/zoea1.00/debug.h (nonexistent)
+++ mips/tags/zoea1.00/debug.h (revision 148)
@@ -0,0 +1,25 @@
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 set_graphmode()
19+#define set_graphmode(m) (0)
20+
21+// Do not use asm("wait") but use asm("nop")
22+#undef WAIT
23+#define WAIT "nop"
24+
25+#endif // __DEBUG
--- mips/tags/zoea1.00/main.c (nonexistent)
+++ mips/tags/zoea1.00/main.c (revision 148)
@@ -0,0 +1,216 @@
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+// main.c
9+// MachiKania BASIC System Ver Zoea
10+// KM-BASIC 統合開発実行環境 for PIC32MX170F256B / PIC32MX270F256B by K.Tanaka
11+
12+// 利用システム
13+// ps2keyboard.X.a : PS/2キーボード入力システムライブラリ
14+// lib_colortext32.a : カラービデオ信号出力システムライブラリ(30×27テキスト版)
15+// libsdfsio.a : SDカードアクセス用ライブラリ
16+
17+#include <xc.h>
18+#include "api.h"
19+#include "compiler.h"
20+#include "editor.h"
21+#include "keyinput.h"
22+#include "main.h"
23+
24+//外付けクリスタル with PLL (16倍)
25+#pragma config PMDL1WAY = OFF, IOL1WAY = OFF
26+#pragma config FPLLIDIV = DIV_1, FPLLMUL = MUL_16, FPLLODIV = DIV_1
27+#pragma config FNOSC = PRIPLL, FSOSCEN = OFF, POSCMOD = XT, OSCIOFNC = OFF
28+#pragma config FPBDIV = DIV_1, FWDTEN = OFF, JTAGEN = OFF, ICESEL = ICS_PGx1
29+#pragma config FCKSM = CSECMD
30+
31+#define mBMXSetRAMKernProgOffset(offset) (BMXDKPBA = (offset))
32+#define mBMXSetRAMUserDataOffset(offset) (BMXDUDBA = (offset))
33+#define mBMXSetRAMUserProgOffset(offset) (BMXDUPBA = (offset))
34+
35+// INIファイル指定キーワード(8文字以内)
36+const char InitKeywords[][9]={
37+ "106KEY","101KEY","NUMLOCK","CAPSLOCK","SCRLLOCK"
38+};
39+
40+void freadline(char *s,FSFILE *fp){
41+// ファイルから1行読み込み、配列sに返す
42+// 最大8文字まで。9文字以上の場合無効
43+// #または0x20以下のコードを見つけた場合、以降は無視
44+// s:9バイト以上の配列
45+// fp:ファイルポインタ
46+ int n;
47+ char c,*p;
48+ n=0;
49+ p=s;
50+ *p=0;
51+ while(n<=8){
52+ if(FSfread(p,1,1,fp)==0 || *p=='\n'){
53+ *p=0;
54+ return;
55+ }
56+ if(*p=='#'){
57+ *p=0;
58+ break;
59+ }
60+ if(*p<=' '){
61+ if(n>0){
62+ *p=0;
63+ break;
64+ }
65+ continue;
66+ }
67+ p++;
68+ n++;
69+ }
70+ if(n>8) *s=0; //9文字以上の文字列の場合は無効
71+ //以降の文字は無視
72+ while(FSfread(&c,1,1,fp) && c!='\n') ;
73+}
74+int searchinittext(char *s){
75+// InitKeywords配列の中から文字列sを探し、位置した場合何番目かを返す
76+// 見つからなかった場合-1を返す
77+ int i;
78+ char *p1;
79+ const char *p2;
80+ for(i=0;i<sizeof(InitKeywords)/sizeof(InitKeywords[0]);i++){
81+ p1=s;
82+ p2=InitKeywords[i];
83+ while(*p1==*p2){
84+ if(*p1==0) return i;
85+ p1++;
86+ p2++;
87+ }
88+ }
89+ return -1;
90+}
91+void readinifile(void){
92+ FSFILE *fp;
93+ char inittext[9];
94+
95+ fp=FSfopen(INIFILE,"r");
96+ if(fp==NULL) return;
97+ printstr("Initialization File Found\n");
98+ lockkey=0; //INIファイルが存在する場合、Lock関連キーはINIファイルに従う
99+ while(1){
100+ if(FSfeof(fp)) break;
101+ freadline(inittext,fp);
102+ switch(searchinittext(inittext)){
103+ case 0:
104+ keytype=0;//日本語キーボード
105+ break;
106+ case 1:
107+ keytype=1;//英語キーボード
108+ break;
109+ case 2:
110+ lockkey|=2;//Num Lock
111+ break;
112+ case 3:
113+ lockkey|=4;//CAPS Lock
114+ break;
115+ case 4:
116+ lockkey|=1;//Scroll Lock
117+ break;
118+ }
119+ }
120+ FSfclose(fp);
121+}
122+
123+void printhex8(unsigned char d){
124+ printchar("0123456789ABCDEF"[d>>4]);
125+ printchar("0123456789ABCDEF"[d&0x0f]);
126+}
127+
128+void printhex16(unsigned short d){
129+ printhex8(d>>8);
130+ printhex8(d&0x00ff);
131+}
132+
133+void printhex32(unsigned int d){
134+ printhex16(d>>16);
135+ printhex16(d&0x0000ffff);
136+}
137+
138+int main(void){
139+ char *appname,*s;
140+
141+ if(DEVCFG1 & 0x8000){
142+ // Set Clock switching enabled and reset
143+ NVMWriteWord(&DEVCFG1,DEVCFG1 & 0xffff7fff);
144+ SoftReset();
145+ }
146+
147+ /* ポートの初期設定 */
148+ TRISA = 0x0000; // PORTA全て出力
149+ ANSELA = 0x0000; // 全てデジタル
150+ TRISB = KEYSTART | KEYFIRE | KEYUP | KEYDOWN | KEYLEFT | KEYRIGHT;// ボタン接続ポート入力設定
151+ ANSELB = 0x0000; // 全てデジタル
152+ CNPUBSET=KEYSTART | KEYFIRE | KEYUP | KEYDOWN | KEYLEFT | KEYRIGHT;// プルアップ設定
153+ ODCB = 0x0300; //RB8,RB9はオープンドレイン
154+
155+ // 周辺機能ピン割り当て
156+ SDI2R=2; //RPA4:SDI2
157+ RPB5R=4; //RPB5:SDO2
158+
159+ // Make RAM executable. See also "char RAM[RAMSIZE]" in globalvars.c
160+ mBMXSetRAMKernProgOffset(PIC32MX_RAMSIZE-RAMSIZE);
161+ mBMXSetRAMUserDataOffset(PIC32MX_RAMSIZE);
162+ mBMXSetRAMUserProgOffset(PIC32MX_RAMSIZE);
163+
164+ ps2mode(); //RA1オン(PS/2有効化マクロ)
165+ init_composite(); // ビデオメモリクリア、割り込み初期化、カラービデオ出力開始
166+ setcursor(0,0,COLOR_NORMALTEXT);
167+
168+ // Show blue screen if exception before soft reset.
169+ blue_screen();
170+
171+ printstr("MachiKania BASIC System\n");
172+ printstr(" Ver "SYSVER1" "SYSVER2" by KENKEN\n");
173+ printstr("BASIC Compiler "BASVER"\n");
174+ printstr(" by Katsumi\n\n");
175+ //SDカードファイルシステム初期化
176+ setcursorcolor(COLOR_NORMALTEXT);
177+ printstr("Init File System...");
178+ // Initialize the File System
179+ if(FSInit()==FALSE){ //ファイルシステム初期化
180+ //エラーの場合停止
181+ setcursorcolor(COLOR_ERRORTEXT);
182+ printstr("\nFile System Error\n");
183+ printstr("Insert Correct Card\n");
184+ printstr("And Reset\n");
185+ while(1) asm("wait");
186+ }
187+ printstr("OK\n");
188+ lockkey=2; // NumLockキーオン
189+ keytype=0; // 日本語キーボード
190+ readinifile(); //INIファイル読み込み
191+ printstr("Init PS/2...");
192+ if(ps2init()){ //PS/2初期化
193+ //キーボードが見つからない場合
194+ printstr("Keyboard Not Found\n");
195+ }
196+ else printstr("OK\n");
197+
198+ wait60thsec(60); //1秒待ち
199+
200+ // 実行中HEXファイル名がHEXFILEと一致した場合はエディタ起動
201+ appname=(char*)FILENAME_FLASH_ADDRESS;
202+ s=HEXFILE;
203+ while(*s++==*appname++) if(*s==0) texteditor(); //テキストエディター呼び出し
204+
205+ // 実行中HEXファイル名の「.HEX」を「.BAS」に置き換えてBASファイルを実行
206+ appname=(char*)FILENAME_FLASH_ADDRESS;
207+ s=tempfile;
208+ while(*appname!='.') *s++=*appname++;
209+ appname=".BAS";
210+ while(*appname!=0) *s++=*appname++;
211+ *s=0;
212+ // buttonmode(); //ボタン有効化
213+ g_disable_break=1; // Breakキー無効化
214+ runbasic(tempfile,0);
215+ while(1) asm(WAIT);
216+}
--- mips/tags/zoea1.00/api.h (nonexistent)
+++ mips/tags/zoea1.00/api.h (revision 148)
@@ -0,0 +1,38 @@
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+#ifndef BOOL
9+ typedef enum _BOOL { FALSE = 0, TRUE } BOOL;
10+#endif
11+
12+#ifndef BYTE
13+ #define BYTE unsigned char
14+#endif
15+
16+#ifndef WORD
17+ #define WORD unsigned short
18+#endif
19+
20+#ifndef DWORD
21+ #define DWORD unsigned long
22+#endif
23+
24+#ifndef UINT16
25+ #define UINT16 unsigned short
26+#endif
27+
28+#ifndef size_t
29+ #define size_t unsigned int
30+#endif
31+
32+// Used for asm("wait")
33+#define WAIT "wait"
34+
35+#include "videoout.h"
36+#include "SDFSIO.h"
37+#include "ps2keyboard.h"
38+#include "debug.h"
--- mips/tags/zoea1.00/operator.c (nonexistent)
+++ mips/tags/zoea1.00/operator.c (revision 148)
@@ -0,0 +1,275 @@
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+Operators: (upper ones have higher priority
12+()
13+* / %
14++ -
15+<< >>
16+< <= > >=
17+= !=
18+XOR
19+AND
20+OR
21+*/
22+
23+
24+const unsigned char g_priority[]={
25+ 0, // OP_VOID
26+ 1, // OP_OR
27+ 2, // OP_AND
28+ 3, // OP_XOR
29+ 4,4, // OP_EQ, OP_NEQ
30+ 5,5,5,5, // OP_LT, OP_LTE, OP_MT, OP_MTE
31+ 6,6, // OP_SHL, OP_SHR
32+ 7,7, // OP_ADD, OP_SUB
33+ 8,8,8 // OP_MUL, OP_DIV, OP_REM
34+};
35+
36+enum operator g_last_op;
37+
38+char* get_operator(void){
39+ char b1,b2,b3;
40+ next_position();
41+ b1=g_source[g_srcpos];
42+ b2=g_source[g_srcpos+1];
43+ b3=g_source[g_srcpos+2];
44+ switch(b1){
45+ case '%': g_last_op=OP_REM; break;
46+ case '/': g_last_op=OP_DIV; break;
47+ case '*': g_last_op=OP_MUL; break;
48+ case '-': g_last_op=OP_SUB; break;
49+ case '+': g_last_op=OP_ADD; break;
50+ case '>':
51+ if (b2=='>') {
52+ g_srcpos++;
53+ g_last_op=OP_SHR;
54+ } else if (b2=='=') {
55+ g_srcpos++;
56+ g_last_op=OP_MTE;
57+ } else {
58+ g_last_op=OP_MT;
59+ }
60+ break;
61+ case '<':
62+ if (b2=='<') {
63+ g_srcpos++;
64+ g_last_op=OP_SHL;
65+ } else if (b2=='=') {
66+ g_srcpos++;
67+ g_last_op=OP_LTE;
68+ } else {
69+ g_last_op=OP_LT;
70+ }
71+ break;
72+ case '!':
73+ if (b2!='=') return ERR_SYNTAX;
74+ g_srcpos++;
75+ g_last_op=OP_NEQ;
76+ break;
77+ case '=':
78+ if (b2=='=') g_srcpos++;
79+ g_last_op=OP_EQ;
80+ break;
81+ case 'X':
82+ if (b2!='O') return ERR_SYNTAX;
83+ if (b3!='R') return ERR_SYNTAX;
84+ g_srcpos++;
85+ g_srcpos++;
86+ g_last_op=OP_XOR;
87+ break;
88+ case 'O':
89+ if (b2!='R') return ERR_SYNTAX;
90+ g_srcpos++;
91+ g_last_op=OP_OR;
92+ break;
93+ case 'A':
94+ if (b2!='N') return ERR_SYNTAX;
95+ if (b3!='D') return ERR_SYNTAX;
96+ g_srcpos++;
97+ g_srcpos++;
98+ g_last_op=OP_AND;
99+ break;
100+ default:
101+ return ERR_SYNTAX;
102+ }
103+ g_srcpos++;
104+ return 0;
105+}
106+
107+char* get_floatOperator(void){
108+ char* err;
109+ int spos;
110+ next_position();
111+ spos=g_srcpos;
112+ err=get_operator();
113+ if (err) return err;
114+ switch(g_last_op){
115+ // Following operators cannot be used for float values.
116+ case OP_XOR:
117+ case OP_REM:
118+ case OP_SHR:
119+ case OP_SHL:
120+ g_srcpos=spos;
121+ return ERR_SYNTAX;
122+ default:
123+ return 0;
124+ }
125+}
126+
127+char* calculation(enum operator op){
128+ // $v0 = $v1 <op> $v0;
129+ switch(op){
130+ case OP_OR:
131+ check_obj_space(1);
132+ g_object[g_objpos++]=0x00621025; // or v0,v1,v0
133+ break;
134+ case OP_AND:
135+ check_obj_space(1);
136+ g_object[g_objpos++]=0x00621024; // and v0,v1,v0
137+ break;
138+ case OP_XOR:
139+ check_obj_space(1);
140+ g_object[g_objpos++]=0x00621026; // xor v0,v1,v0
141+ break;
142+ case OP_EQ:
143+ check_obj_space(2);
144+ g_object[g_objpos++]=0x00621026; // xor v0,v1,v0
145+ g_object[g_objpos++]=0x2C420001; // sltiu v0,v0,1
146+ break;
147+ case OP_NEQ:
148+ check_obj_space(2);
149+ g_object[g_objpos++]=0x00621026; // xor v0,v1,v0
150+ g_object[g_objpos++]=0x0002102B; // sltu v0,zero,v0
151+ break;
152+ case OP_LT:
153+ check_obj_space(1);
154+ g_object[g_objpos++]=0x0062102A; // slt v0,v1,v0
155+ break;
156+ case OP_LTE:
157+ check_obj_space(2);
158+ g_object[g_objpos++]=0x0043102A; // slt v0,v0,v1
159+ g_object[g_objpos++]=0x38420001; // xori v0,v0,0x1
160+ break;
161+ case OP_MT:
162+ check_obj_space(1);
163+ g_object[g_objpos++]=0x0043102A; // slt v0,v0,v1
164+ break;
165+ case OP_MTE:
166+ check_obj_space(2);
167+ g_object[g_objpos++]=0x0062102A; // slt v0,v1,v0
168+ g_object[g_objpos++]=0x38420001; // xori v0,v0,0x1
169+ break;
170+ case OP_SHR:
171+ check_obj_space(1);
172+ g_object[g_objpos++]=0x00431006; // srlv v0,v1,v0
173+ break;
174+ case OP_SHL:
175+ check_obj_space(1);
176+ g_object[g_objpos++]=0x00431004; // sllv v0,v1,v0
177+ break;
178+ case OP_ADD:
179+ check_obj_space(1);
180+ g_object[g_objpos++]=0x00621021; // addu v0,v1,v0
181+ break;
182+ case OP_SUB:
183+ check_obj_space(1);
184+ g_object[g_objpos++]=0x00621023; // subu v0,v1,v0
185+ break;
186+ case OP_MUL:
187+ check_obj_space(1);
188+ g_object[g_objpos++]=0x70621002; // mul v0,v1,v0
189+ break;
190+ case OP_DIV:
191+ // Note that intterupt functions do not use mflo and mfhi.
192+ // Probably using div does not cause delay of interrupt.
193+ check_obj_space(5);
194+ g_object[g_objpos++]=0x14400003; // bne v0,zero,label
195+ g_object[g_objpos++]=0x0062001A; // div v1,v0
196+ call_lib_code(LIB_DIV0); // 2 words
197+ // label:
198+ g_object[g_objpos++]=0x00001012; // mflo v0
199+ break;
200+ case OP_REM:
201+ check_obj_space(5);
202+ g_object[g_objpos++]=0x14400003; // bne v0,zero,label
203+ g_object[g_objpos++]=0x0062001A; // div v1,v0
204+ call_lib_code(LIB_DIV0); // 2 words
205+ // label:
206+ g_object[g_objpos++]=0x00001010; // mfhi v0
207+ break;
208+ default:
209+ return ERR_SYNTAX;
210+ }
211+ return 0;
212+}
213+
214+char* calculation_float(enum operator op){
215+ // $v0 = $a0 <op> $v0;
216+ check_obj_space(1);
217+ g_object[g_objpos++]=0x34050000|(op&0x0000FFFF); // ori a1,zero,xxxx
218+ // All the calculations will be done in library code, lib_float function (see below).
219+ call_lib_code(LIB_FLOAT);
220+ return 0;
221+}
222+
223+int lib_float(int ia0,int iv0, enum operator a1){
224+ // This function was called from _call_library().
225+ // Variable types must be all int.
226+ // Casting cannot be used.
227+ // Instead, by using pointer, put as int value, get as float value,
228+ // calculate, put as float value, then get as int value for returning.
229+ volatile float a0,v0;
230+ ((int*)(&a0))[0]=ia0;
231+ ((int*)(&v0))[0]=iv0;
232+ switch(a1){
233+ case OP_EQ:
234+ v0= a0==v0?1:0;
235+ break;
236+ case OP_NEQ:
237+ v0= a0!=v0?1:0;
238+ break;
239+ case OP_LT:
240+ v0= a0<v0?1:0;
241+ break;
242+ case OP_LTE:
243+ v0= a0<=v0?1:0;
244+ break;
245+ case OP_MT:
246+ v0= a0>v0?1:0;
247+ break;
248+ case OP_MTE:
249+ v0= a0>=v0?1:0;
250+ break;
251+ case OP_ADD:
252+ v0= a0+v0;
253+ break;
254+ case OP_SUB:
255+ v0= a0-v0;
256+ break;
257+ case OP_MUL:
258+ v0= a0*v0;
259+ break;
260+ case OP_DIV:
261+ if (v0==0) err_div_zero();
262+ v0= a0/v0;
263+ break;
264+ case OP_OR:
265+ v0= a0||v0?1:0;
266+ break;
267+ case OP_AND:
268+ v0= a0&&v0?1:0;
269+ break;
270+ default:
271+ err_unknown();
272+ return 0;
273+ }
274+ return ((int*)(&v0))[0];
275+};
\ No newline at end of file
--- mips/tags/zoea1.00/memory.c (nonexistent)
+++ mips/tags/zoea1.00/memory.c (revision 148)
@@ -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+#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+}
\ No newline at end of file
--- mips/tags/zoea1.00/keyinput.c (nonexistent)
+++ mips/tags/zoea1.00/keyinput.c (revision 148)
@@ -0,0 +1,199 @@
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+// キー入力、カーソル表示関連機能 by K.Tanaka
7+// PS/2キーボード入力システム、カラーテキスト出力システム利用
8+
9+#include "videoout.h"
10+#include "ps2keyboard.h"
11+#include "keyinput.h"
12+
13+unsigned char lineinputbuf[256]; //lineinput関数用一時バッファ
14+unsigned char blinkchar,blinkcolor;
15+int blinktimer;
16+int insertmode; //挿入モード:1、上書きモード:0
17+
18+void getcursorchar(){
19+// カーソル点滅用に元の文字コードを退避
20+ blinkchar=*cursor;
21+ blinkcolor=*(cursor+ATTROFFSET);
22+}
23+void resetcursorchar(){
24+// カーソルを元の文字に戻す
25+ *cursor=blinkchar;
26+ *(cursor+ATTROFFSET)=blinkcolor;
27+}
28+void blinkcursorchar(){
29+// 定期的に呼び出すことでカーソルを点滅表示させる
30+// BLINKTIMEで点滅間隔を設定
31+// 事前にgetcursorchar()を呼び出しておく
32+ blinktimer++;
33+ if(blinktimer>=BLINKTIME*2) blinktimer=0;
34+ if(blinktimer<BLINKTIME){
35+ if(insertmode) *cursor=CURSORCHAR;
36+ else *cursor=CURSORCHAR2;
37+ *(cursor+ATTROFFSET)=CURSORCOLOR;
38+ }
39+ else{
40+ *cursor=blinkchar;
41+ *(cursor+ATTROFFSET)=blinkcolor;
42+ }
43+}
44+
45+unsigned char inputchar(void){
46+// キーボードから1キー入力待ち
47+// 戻り値 通常文字の場合ASCIIコード、その他は0、グローバル変数vkeyに仮想キーコード
48+ unsigned char k;
49+ unsigned short d;
50+ d=drawcount;
51+ while(1){
52+ while(d==drawcount) asm("wait"); //60分の1秒ウェイト
53+ d=drawcount;
54+ k=ps2readkey(); //キーバッファから読み込み、k1:通常文字入力の場合ASCIIコード
55+ if(vkey) return k;
56+ }
57+}
58+
59+unsigned char cursorinputchar(void){
60+// カーソル表示しながらキーボードから1キー入力待ち
61+// 戻り値 通常文字の場合ASCIIコード、その他は0、グローバル変数vkeyに仮想キーコード
62+ unsigned char k;
63+ unsigned short d;
64+ getcursorchar(); //カーソル位置の文字を退避(カーソル点滅用)
65+ d=drawcount;
66+ while(1){
67+ while(d==drawcount) asm("wait"); //60分の1秒ウェイト
68+ d=drawcount;
69+ blinkcursorchar(); //カーソル点滅させる
70+ k=ps2readkey(); //キーバッファから読み込み、k1:通常文字入力の場合ASCIIコード
71+ if(vkey) break; //キーが押された場合ループから抜ける
72+ }
73+ resetcursorchar(); //カーソルを元の文字表示に戻す
74+ return k;
75+}
76+
77+unsigned char printinputchar(void){
78+// カーソル表示しながらキーボードから通常文字キー入力待ちし、入力された文字を表示
79+// 戻り値 入力された文字のASCIIコード、グローバル変数vkeyに最後に押されたキーの仮想キーコード
80+ unsigned char k;
81+ while(1){
82+ k=cursorinputchar();
83+ if(k) break;
84+ }
85+ printchar(k);
86+ return k;
87+}
88+
89+int lineinput(char *s,int n){
90+// キー入力して文字列配列sに格納
91+// sに初期文字列を入れておくと最初に表示して文字列の最後にカーソル移動する
92+// 初期文字列を使用しない場合は*s=0としておく
93+// カーソル位置はsetcursor関数で指定しておく
94+// 最大文字数n、最後に0を格納するのでn+1バイトの領域必要、ただしnの最大値は255
95+// 戻り値 Enterで終了した場合0、ESCで終了時は-1(sは壊さない)
96+//
97+ unsigned char *ps,*pd,*pc;
98+ unsigned char k1,k2;
99+ int i;
100+
101+ if(n>255) return -1;
102+ ps=s;
103+ pd=lineinputbuf;
104+ i=0;
105+ //初期文字列をlineinputbufにコピーし、文字数をiに入れる
106+ while(*ps!=0 && i<n){
107+ *pd++=*ps++;
108+ i++;
109+ }
110+ *pd=0;//バッファ内の文字列最後に0
111+ pc=pd;//現在の文字入力位置ポインタ(最後尾)
112+ if(i>0) printstr(lineinputbuf); //初期文字列表示
113+ while(1){
114+ k1=cursorinputchar(); //カーソル表示しながら1キー入力待ち
115+ k2=(unsigned char)vkey; //k2:仮想キーコード
116+ if(k1){
117+ //通常文字の場合
118+ if(insertmode || *pc==0){
119+ //挿入モードまたは最後尾の場合
120+ if(i==n) continue; //入力文字数最大値の場合無視
121+ for(pd=lineinputbuf+i;pd>=pc;pd--) *(pd+1)=*pd; //1文字分挿入
122+ i++;
123+ }
124+ *pc=k1; //入力文字を追加
125+ printstr(pc); //入力文字以降を表示
126+ pc++;
127+ for(ps=lineinputbuf+i;ps>pc;ps--) cursor--; //カーソル位置戻し
128+ }
129+ else switch(k2){
130+ //制御文字の場合
131+ case VK_LEFT:
132+ case VK_NUMPAD4:
133+ //左矢印キー
134+ if(pc>lineinputbuf){
135+ pc--;
136+ cursor--;
137+ }
138+ break;
139+ case VK_RIGHT:
140+ case VK_NUMPAD6:
141+ //右矢印キー
142+ if(*pc!=0){
143+ pc++;
144+ cursor++;
145+ }
146+ break;
147+ case VK_RETURN: //Enterキー
148+ case VK_SEPARATOR: //テンキーのEnter
149+ //入力用バッファから呼び出し元のバッファにコピーして終了
150+ printchar('\n');
151+ ps=lineinputbuf;
152+ pd=s;
153+ while(*ps!=0) *pd++=*ps++;
154+ *pd=0;
155+ return 0;
156+ case VK_HOME:
157+ case VK_NUMPAD7:
158+ //Homeキー、文字列先頭にカーソル移動
159+ while(pc>lineinputbuf){
160+ pc--;
161+ cursor--;
162+ }
163+ break;
164+ case VK_END:
165+ case VK_NUMPAD1:
166+ //Endキー、文字列最後尾にカーソル移動
167+ while(*pc!=0){
168+ pc++;
169+ cursor++;
170+ }
171+ break;
172+ case VK_BACK:
173+ //Back Spaceキー、1文字左に移動しDelete処理
174+ if(pc==lineinputbuf) break;//カーソルが先頭の場合、無視
175+ pc--;
176+ cursor--;
177+ case VK_DELETE:
178+ case VK_DECIMAL:
179+ //Deleteキー、カーソル位置の1文字削除
180+ if(*pc==0) break;//カーソルが最後尾の場合、無視
181+ for(pd=pc;*(pd+1)!=0;pd++) *pd=*(pd+1);
182+ *pd=0;
183+ i--;
184+ printstr(pc);
185+ printchar(0);//NULL文字表示
186+ for(ps=lineinputbuf+i+1;ps>pc;ps--) cursor--;
187+ break;
188+ case VK_INSERT:
189+ case VK_NUMPAD0:
190+ //Insertキー、挿入モードトグル動作
191+ insertmode^=1;
192+ break;
193+ case VK_ESCAPE:
194+ case VK_CANCEL:
195+ //ESCキーまたはCTRL+Breakキー、-1で終了
196+ return -1;
197+ }
198+ }
199+}
--- mips/tags/zoea1.00/ps2keyboard.h (nonexistent)
+++ mips/tags/zoea1.00/ps2keyboard.h (revision 148)
@@ -0,0 +1,174 @@
1+#define CHK_SHIFT 0x01
2+#define CHK_CTRL 0x02
3+#define CHK_ALT 0x04
4+#define CHK_WIN 0x08
5+#define CHK_SCRLK 0x10
6+#define CHK_NUMLK 0x20
7+#define CHK_CAPSLK 0x40
8+#define CHK_SHIFT_L 0x01
9+#define CHK_SHIFT_R 0x02
10+#define CHK_CTRL_L 0x04
11+#define CHK_CTRL_R 0x08
12+#define CHK_ALT_L 0x10
13+#define CHK_ALT_R 0x20
14+#define CHK_WIN_L 0x40
15+#define CHK_WIN_R 0x80
16+#define CHK_SCRLK_A 0x100
17+#define CHK_NUMLK_A 0x200
18+#define CHK_CAPSLK_A 0x400
19+
20+#define VK_LBUTTON 0x01
21+#define VK_RBUTTON 0x02
22+#define VK_CANCEL 0x03
23+#define VK_MBUTTON 0x04
24+#define VK_XBUTTON1 0x05
25+#define VK_XBUTTON2 0x06
26+#define VK_BACK 0x08
27+#define VK_TAB 0x09
28+#define VK_CLEAR 0x0C
29+#define VK_RETURN 0x0D
30+#define VK_SHIFT 0x10
31+#define VK_CONTROL 0x11
32+#define VK_MENU 0x12
33+#define VK_PAUSE 0x13
34+#define VK_CAPITAL 0x14
35+#define VK_KANA 0x15
36+#define VK_HANGUEL 0x15
37+#define VK_HANGUL 0x15
38+#define VK_JUNJA 0x17
39+#define VK_FINAL 0x18
40+#define VK_HANJA 0x19
41+#define VK_KANJI 0x19
42+#define VK_ESCAPE 0x1B
43+#define VK_CONVERT 0x1C
44+#define VK_NONCONVERT 0x1D
45+#define VK_ACCEPT 0x1E
46+#define VK_MODECHANGE 0x1F
47+#define VK_SPACE 0x20
48+#define VK_PRIOR 0x21
49+#define VK_NEXT 0x22
50+#define VK_END 0x23
51+#define VK_HOME 0x24
52+#define VK_LEFT 0x25
53+#define VK_UP 0x26
54+#define VK_RIGHT 0x27
55+#define VK_DOWN 0x28
56+#define VK_SELECT 0x29
57+#define VK_PRINT 0x2A
58+#define VK_EXECUTE 0x2B
59+#define VK_SNAPSHOT 0x2C
60+#define VK_INSERT 0x2D
61+#define VK_DELETE 0x2E
62+#define VK_HELP 0x2F
63+#define VK_LWIN 0x5B
64+#define VK_RWIN 0x5C
65+#define VK_APPS 0x5D
66+#define VK_SLEEP 0x5F
67+#define VK_NUMPAD0 0x60
68+#define VK_NUMPAD1 0x61
69+#define VK_NUMPAD2 0x62
70+#define VK_NUMPAD3 0x63
71+#define VK_NUMPAD4 0x64
72+#define VK_NUMPAD5 0x65
73+#define VK_NUMPAD6 0x66
74+#define VK_NUMPAD7 0x67
75+#define VK_NUMPAD8 0x68
76+#define VK_NUMPAD9 0x69
77+#define VK_MULTIPLY 0x6A
78+#define VK_ADD 0x6B
79+#define VK_SEPARATOR 0x6C
80+#define VK_SUBTRACT 0x6D
81+#define VK_DECIMAL 0x6E
82+#define VK_DIVIDE 0x6F
83+#define VK_F1 0x70
84+#define VK_F2 0x71
85+#define VK_F3 0x72
86+#define VK_F4 0x73
87+#define VK_F5 0x74
88+#define VK_F6 0x75
89+#define VK_F7 0x76
90+#define VK_F8 0x77
91+#define VK_F9 0x78
92+#define VK_F10 0x79
93+#define VK_F11 0x7A
94+#define VK_F12 0x7B
95+#define VK_F13 0x7C
96+#define VK_F14 0x7D
97+#define VK_F15 0x7E
98+#define VK_F16 0x7F
99+#define VK_F17 0x80
100+#define VK_F18 0x81
101+#define VK_F19 0x82
102+#define VK_F20 0x83
103+#define VK_F21 0x84
104+#define VK_F22 0x85
105+#define VK_F23 0x86
106+#define VK_F24 0x87
107+#define VK_NUMLOCK 0x90
108+#define VK_SCROLL 0x91
109+#define VK_LSHIFT 0xA0
110+#define VK_RSHIFT 0xA1
111+#define VK_LCONTROL 0xA2
112+#define VK_RCONTROL 0xA3
113+#define VK_LMENU 0xA4
114+#define VK_RMENU 0xA5
115+#define VK_BROWSER_BACK 0xA6
116+#define VK_BROWSER_FORWARD 0xA7
117+#define VK_BROWSER_REFRESH 0xA8
118+#define VK_BROWSER_STOP 0xA9
119+#define VK_BROWSER_SEARCH 0xAA
120+#define VK_BROWSER_FAVORITES 0xAB
121+#define VK_BROWSER_HOME 0xAC
122+#define VK_VOLUME_MUTE 0xAD
123+#define VK_VOLUME_DOWN 0xAE
124+#define VK_VOLUME_UP 0xAF
125+#define VK_MEDIA_NEXT_TRACK 0xB0
126+#define VK_MEDIA_PREV_TRACK 0xB1
127+#define VK_MEDIA_STOP 0xB2
128+#define VK_MEDIA_PLAY_PAUSE 0xB3
129+#define VK_LAUNCH_MAIL 0xB4
130+#define VK_LAUNCH_MEDIA_SELECT 0xB5
131+#define VK_LAUNCH_APP1 0xB6
132+#define VK_LAUNCH_APP2 0xB7
133+#define VK_OEM_1 0xBA
134+#define VK_OEM_PLUS 0xBB
135+#define VK_OEM_COMMA 0xBC
136+#define VK_OEM_MINUS 0xBD
137+#define VK_OEM_PERIOD 0xBE
138+#define VK_OEM_2 0xBF
139+#define VK_OEM_3 0xC0
140+#define VK_OEM_4 0xDB
141+#define VK_OEM_5 0xDC
142+#define VK_OEM_6 0xDD
143+#define VK_OEM_7 0xDE
144+#define VK_OEM_8 0xDF
145+#define VK_OEM_102 0xE2
146+#define VK_PROCESSKEY 0xE5
147+#define VK_PACKE 0xE7
148+#define VK_ATTN 0xF6
149+#define VK_CRSEL 0xF7
150+#define VK_EXSEL 0xF8
151+#define VK_EREOF 0xF9
152+#define VK_PLAY 0xFA
153+#define VK_ZOOM 0xFB
154+#define VK_NONAME 0xFC
155+#define VK_PA1 0xFD
156+#define VK_OEM_CLEAR 0xFE
157+
158+extern volatile unsigned char ps2keystatus[256]; // 仮想コードに相当するキーの状態(Onの時1)
159+extern volatile unsigned short vkey; //仮想キーコード
160+extern unsigned char lockkey; // 初期化時にLockキーの状態指定。下位3ビットが<CAPSLK><NUMLK><SCRLK>
161+extern unsigned char keytype; // キーボードの種類。0:日本語109キー、1:英語104キー
162+
163+int ps2init(); // PS/2ライブラリ関連初期化。正常終了0、エラーで-1を返す
164+unsigned char shiftkeys(); // SHIFT関連キーの押下状態を返す
165+unsigned char ps2readkey();
166+// 入力された1つのキーのキーコードをグローバル変数vkeyに格納(押されていなければ0を返す)
167+// 下位8ビット:キーコード
168+// 上位8ビット:シフト状態(押下:1)、上位から<0><CAPSLK><NUMLK><SCRLK><Win><ALT><CTRL><SHIFT>
169+// 英数・記号文字の場合、戻り値としてASCIIコード(それ以外は0を返す)
170+
171+// PIC32MX1xx/2xx版のキーボードとボタンの排他利用システムで使用する関数、マクロ
172+void ps2mode(); // PS/2を有効にする
173+void buttonmode(); // ボタンを有効にする
174+#define inPS2MODE() ((LATA&2)>>1) // モード確認用マクロ。PS/2モードの場合1、ボタンモードの場合0を返す
--- mips/tags/zoea1.00/keyinput.h (nonexistent)
+++ mips/tags/zoea1.00/keyinput.h (revision 148)
@@ -0,0 +1,45 @@
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+#define BLINKTIME 15
8+#define CURSORCHAR 0x87
9+#define CURSORCHAR2 0x80
10+#define CURSORCOLOR 7
11+
12+void getcursorchar();
13+// カーソル点滅用に元の文字コードを退避
14+
15+void resetcursorchar();
16+// カーソルを元の文字に戻す
17+
18+void blinkcursorchar();
19+// 定期的に呼び出すことでカーソルを点滅表示させる
20+// BLINKTIMEで点滅間隔を設定
21+// 事前にgetcursorchar()を呼び出しておく
22+
23+int lineinput(char *s,int n);
24+// キー入力して文字列配列sに格納
25+// sに初期文字列を入れておくと最初に表示して文字列の最後にカーソル移動する
26+// 初期文字列を使用しない場合は*s=0としておく
27+// カーソル位置はsetcursor関数で指定しておく
28+// 最大文字数n、最後に0を格納するのでn+1バイトの領域必要、ただしnの最大値は255
29+// 戻り値 Enterで終了した場合0、ESCで終了時は-1(sは壊さない)
30+
31+unsigned char inputchar(void);
32+// キーボードから1キー入力待ち
33+// 戻り値 通常文字の場合ASCIIコード、その他は0、グローバル変数vkeyに仮想キーコード
34+
35+unsigned char printinputchar(void);
36+// カーソル表示しながらキーボードから通常文字キー入力待ちし、入力された文字を表示
37+// 戻り値 入力された文字のASCIIコード、グローバル変数vkeyに最後に押されたキーの仮想キーコード
38+
39+unsigned char cursorinputchar(void);
40+// カーソル表示しながらキーボードから1キー入力待ち
41+// 戻り値 通常文字の場合ASCIIコード、その他は0、グローバル変数vkeyに仮想キーコード
42+
43+extern unsigned char blinkchar,blinkcolor;
44+extern int blinktimer;
45+extern int insertmode; //挿入モード:1、上書きモード:0
--- mips/tags/zoea1.00/SDFSIO.h (nonexistent)
+++ mips/tags/zoea1.00/SDFSIO.h (revision 148)
@@ -0,0 +1,2344 @@
1+/******************************************************************************
2+ *
3+ * Microchip Memory Disk Drive File System
4+ *
5+ ******************************************************************************
6+ * FileName: FSIO.h
7+ * Dependencies: GenericTypeDefs.h
8+ * FSconfig.h
9+ * FSDefs.h
10+ * stddef.h
11+ * Processor: PIC18/PIC24/dsPIC30/dsPIC33/PIC32
12+ * Compiler: C18/C30/C32
13+ * Company: Microchip Technology, Inc.
14+ * Version: 1.3.0
15+ *
16+ * Software License Agreement
17+ *
18+ * The software supplied herewith by Microchip Technology Incorporated
19+ * (the 鼎ompany・ for its PICmicroョ Microcontroller is intended and
20+ * supplied to you, the Company痴 customer, for use solely and
21+ * exclusively on Microchip PICmicro Microcontroller products. The
22+ * software is owned by the Company and/or its supplier, and is
23+ * protected under applicable copyright laws. All rights are reserved.
24+ * Any use in violation of the foregoing restrictions may subject the
25+ * user to criminal sanctions under applicable laws, as well as to
26+ * civil liability for the breach of the terms and conditions of this
27+ * license.
28+ *
29+ * THIS SOFTWARE IS PROVIDED IN AN 鄭S IS・CONDITION. NO WARRANTIES,
30+ * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
31+ * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
32+ * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
33+ * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
34+ * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
35+ *
36+*****************************************************************************/
37+
38+#ifndef FS_DOT_H
39+#define FS_DOT_H
40+
41+#define ALLOW_FILESEARCH
42+#define ALLOW_WRITES
43+#define ALLOW_DIRS
44+#define SUPPORT_FAT32
45+
46+#define MDD_MediaInitialize MDD_SDSPI_MediaInitialize
47+#define MDD_MediaDetect MDD_SDSPI_MediaDetect
48+#define MDD_SectorRead MDD_SDSPI_SectorRead
49+#define MDD_SectorWrite MDD_SDSPI_SectorWrite
50+#define MDD_InitIO MDD_SDSPI_InitIO
51+#define MDD_ShutdownMedia MDD_SDSPI_ShutdownMedia
52+#define MDD_WriteProtectState MDD_SDSPI_WriteProtectState
53+
54+// Summary: An enumeration used for various error codes.
55+// Description: The CETYPE enumeration is used to indicate different error conditions during device operation.
56+typedef enum _CETYPE
57+{
58+ CE_GOOD = 0, // No error
59+ CE_ERASE_FAIL, // An erase failed
60+ CE_NOT_PRESENT, // No device was present
61+ CE_NOT_FORMATTED, // The disk is of an unsupported format
62+ CE_BAD_PARTITION, // The boot record is bad
63+ CE_UNSUPPORTED_FS, // The file system type is unsupported
64+ CE_INIT_ERROR, // An initialization error has occured
65+ CE_NOT_INIT, // An operation was performed on an uninitialized device
66+ CE_BAD_SECTOR_READ, // A bad read of a sector occured
67+ CE_WRITE_ERROR, // Could not write to a sector
68+ CE_INVALID_CLUSTER, // Invalid cluster value > maxcls
69+ CE_FILE_NOT_FOUND, // Could not find the file on the device
70+ CE_DIR_NOT_FOUND, // Could not find the directory
71+ CE_BAD_FILE, // File is corrupted
72+ CE_DONE, // No more files in this directory
73+ CE_COULD_NOT_GET_CLUSTER, // Could not load/allocate next cluster in file
74+ CE_FILENAME_2_LONG, // A specified file name is too long to use
75+ CE_FILENAME_EXISTS, // A specified filename already exists on the device
76+ CE_INVALID_FILENAME, // Invalid file name
77+ CE_DELETE_DIR, // The user tried to delete a directory with FSremove
78+ CE_DIR_FULL, // All root dir entry are taken
79+ CE_DISK_FULL, // All clusters in partition are taken
80+ CE_DIR_NOT_EMPTY, // This directory is not empty yet, remove files before deleting
81+ CE_NONSUPPORTED_SIZE, // The disk is too big to format as FAT16
82+ CE_WRITE_PROTECTED, // Card is write protected
83+ CE_FILENOTOPENED, // File not opened for the write
84+ CE_SEEK_ERROR, // File location could not be changed successfully
85+ CE_BADCACHEREAD, // Bad cache read
86+ CE_CARDFAT32, // FAT 32 - card not supported
87+ CE_READONLY, // The file is read-only
88+ CE_WRITEONLY, // The file is write-only
89+ CE_INVALID_ARGUMENT, // Invalid argument
90+ CE_TOO_MANY_FILES_OPEN, // Too many files are already open
91+ CE_UNSUPPORTED_SECTOR_SIZE // Unsupported sector size
92+} CETYPE;
93+
94+
95+// Summary: A macro indicating a dir entry was found
96+// Description: The FOUND macro indicates that a directory entry was found in the specified position
97+#define FOUND 0
98+
99+// Summary: A macro indicating no dir entry was found
100+// Description: The NOT_FOUND macro indicates that the specified directory entry to load was deleted
101+#define NOT_FOUND 1
102+
103+// Summary: A macro indicating that no more files were found
104+// Description: The NO_MORE macro indicates that there are no more directory entries to search for
105+#define NO_MORE 2
106+
107+
108+
109+// Summary: A macro indicating the device is formatted with FAT12
110+// Description: The FAT12 macro is used to indicate that the file system on the device being accessed is a FAT12 file system.
111+#define FAT12 1
112+
113+// Summary: A macro indicating the device is formatted with FAT16
114+// Description: The FAT16 macro is used to indicate that the file system on the device being accessed is a FAT16 file system.
115+#define FAT16 2
116+
117+// Summary: A macro indicating the device is formatted with FAT32
118+// Description: The FAT32 macro is used to indicate that the file system on the device being accessed is a FAT32 file system.
119+#define FAT32 3
120+
121+
122+
123+// Summary: A read-only attribute macro
124+// Description: A macro for the read-only attribute. A file with this attribute should not be written to. Note that this
125+// attribute will not actually prevent a write to the file; that functionality is operating-system dependant. The
126+// user should take care not to write to a read-only file.
127+#define ATTR_READ_ONLY 0x01
128+
129+// Summary: A hidden attribute macro
130+// Description: A macro for the hidden attribute. A file with this attribute may be hidden from the user, depending on the
131+// implementation of the operating system.
132+#define ATTR_HIDDEN 0x02
133+
134+// Summary: A system attribute macro
135+// Description: A macro for the system attribute. A file with this attribute is used by the operating system, and should not be
136+// modified. Note that this attribute will not actually prevent a write to the file.
137+#define ATTR_SYSTEM 0x04
138+
139+// Summary: A volume attribute macro
140+// Description: A macro for the volume attribute. If the first directory entry in the root directory has the volume attribute set,
141+// the device will use the name in that directory entry as the volume name.
142+#define ATTR_VOLUME 0x08
143+
144+// Summary: A macro for the attributes for a long-file name entry
145+// Description: A macro for the long-name attributes. If a directory entry is used in a long-file name implementation, it will have
146+// all four lower bits set. This indicates that any software that does not support long file names should ignore that
147+// entry.
148+#define ATTR_LONG_NAME 0x0f
149+
150+// Summary: A directory attribute macro
151+// Description: A macro for the directory attribute. If a directory entry has this attribute set, the file it points to is a directory-
152+// type file, and will contain directory entries that point to additional directories or files.
153+#define ATTR_DIRECTORY 0x10
154+
155+// Summary: An archive attribute macro
156+// Description: A macro for the archive attribute. This attribute will indicate to some archiving programs that the file with this
157+// attribute needs to be backed up. Most operating systems create files with the archive attribute set.
158+#define ATTR_ARCHIVE 0x20
159+
160+// Summary: A macro for all attributes
161+// Description: A macro for all attributes. The search functions in this library require an argument that determines which attributes
162+// a file is allowed to have in order to be found. If ATTR_MASK is specified as this argument, any file may be found, regardless
163+// of its attributes.
164+#define ATTR_MASK 0x3f
165+
166+
167+
168+// Summary: A macro to indicate an empty FAT entry
169+// Description: The CLUSTER_EMPTY value is used to indicate that a FAT entry and it's corresponding cluster are available.
170+#define CLUSTER_EMPTY 0x0000
171+
172+// Summary: A macro to indicate the last cluster value for FAT12
173+// Description: The LAST_CLUSTER_FAT12 macro is used when reading the FAT to indicate that the next FAT12 entry for a file contains
174+// the end-of-file value.
175+#define LAST_CLUSTER_FAT12 0xff8
176+
177+// Summary: A macro to indicate the last cluster value for FAT16
178+// Description: The LAST_CLUSTER_FAT16 macro is used when reading the FAT to indicate that the next FAT16 entry for a file contains
179+// the end-of-file value.
180+#define LAST_CLUSTER_FAT16 0xfff8
181+
182+// Summary: A macro to indicate the last allocatable cluster for FAT12
183+// Description: The END_CLUSTER_FAT12 value is used as a comparison in FAT12 to determine that the firmware has reached the end of
184+// the range of allowed allocatable clusters.
185+#define END_CLUSTER_FAT12 0xFF7
186+
187+// Summary: A macro to indicate the last allocatable cluster for FAT16
188+// Description: The END_CLUSTER_FAT16 value is used as a comparison in FAT16 to determine that the firmware has reached the end of
189+// the range of allowed allocatable clusters.
190+#define END_CLUSTER_FAT16 0xFFF7
191+
192+// Summary: A macro to indicate the failure of the ReadFAT function
193+// Description: The CLUSTER_FAIL_FAT16 macro is used by the ReadFAT function to indicate that an error occured reading a FAT12 or FAT16
194+// file allocation table. Note that since '0xFFF8' is used for the last cluster return value in the FAT16 implementation
195+// the end-of-file value '0xFFFF' can be used to indicate an error condition.
196+#define CLUSTER_FAIL_FAT16 0xFFFF
197+
198+
199+
200+#ifdef SUPPORT_FAT32
201+ // Summary: A macro to indicate the last cluster value for FAT32
202+ // Description: The LAST_CLUSTER_FAT32 macro is used when reading the FAT to indicate that the next FAT32 entry for a file contains
203+ // the end-of-file value.
204+ #define LAST_CLUSTER_FAT32 0x0FFFFFF8
205+
206+ // Summary: A macro to indicate the last allocatable cluster for FAT32
207+ // Description: The END_CLUSTER_FAT32 value is used as a comparison in FAT32 to determine that the firmware has reached the end of
208+ // the range of allowed allocatable clusters.
209+ #define END_CLUSTER_FAT32 0x0FFFFFF7
210+
211+ // Summary: A macro to indicate the failure of the ReadFAT function
212+ // Description: The CLUSTER_FAIL_FAT32 macro is used by the ReadFAT function to indicate that an error occured reading a FAT32
213+ // file allocation able.
214+ #define CLUSTER_FAIL_FAT32 0x0FFFFFFF
215+
216+#endif
217+
218+// Summary: A macro indicating the number of bytes in a directory entry.
219+// Description: The NUMBER_OF_BYTES_IN_DIR_ENTRY macro represents the number of bytes in one directory entry. It is used to calculate
220+// the number of sectors in the root directory based on information in the boot sector.
221+#define NUMBER_OF_BYTES_IN_DIR_ENTRY 32
222+
223+
224+
225+// Summary: A macro for a deleted dir entry marker.
226+// Description: The DIR_DEL macro is used to mark a directory entry as deleted. When a file is deleted, this value will replace the
227+// first character in the file name, and will indicate that the file the entry points to was deleted.
228+#define DIR_DEL 0xE5
229+
230+// Summary: A macro for the last dir entry marker.
231+// Description: The DIR_EMPTY macro is used to indicate the last entry in a directory. Since entries in use cannot start with a 0 and
232+// deleted entries start with the DIR_DEL character, a 0 will mark the end of the in-use or previously used group of
233+// entries in a directory
234+#define DIR_EMPTY 0
235+
236+
237+
238+// Summary: A macro used to indicate the length of an 8.3 file name
239+// Description: The DIR_NAMESIZE macro is used when validing the name portion of 8.3 filenames
240+#define DIR_NAMESIZE 8
241+
242+// Summary: A macro used to indicate the length of an 8.3 file extension
243+// Description: The DIR_EXTENSION macro is used when validating the extension portion of 8.3 filenames
244+#define DIR_EXTENSION 3
245+
246+// Summary: A macro used to indicate the length of an 8.3 file name and extension
247+// Description: The DIR_NAMECOMP macro is used when validating 8.3 filenames
248+#define DIR_NAMECOMP (DIR_NAMESIZE+DIR_EXTENSION)
249+
250+
251+
252+// Summary: A macro to write a byte to RAM
253+// Description: The RAMwrite macro is used to write a byte of data to a RAM array
254+#define RAMwrite( a, f, d) *(a+f) = d
255+
256+// Summary: A macro to read a byte from RAM
257+// Description: The RAMread macro is used to read a byte of data from a RAM array
258+#define RAMread( a, f) *(a+f)
259+
260+// Summary: A macro to read a 16-bit word from RAM
261+// Description: The RAMreadW macro is used to read two bytes of data from a RAM array
262+#define RAMreadW( a, f) *(WORD *)(a+f)
263+
264+// Summary: A macro to read a 32-bit word from RAM
265+// Description: The RAMreadD macro is used to read four bytes of data from a RAM array
266+#define RAMreadD( a, f) *(DWORD *)(a+f)
267+
268+
269+
270+#ifndef EOF
271+ // Summary: Indicates error conditions or end-of-file conditions
272+ // Description: The EOF macro is used to indicate error conditions in some function calls. It is also used to indicate
273+ // that the end-of-file has been reached.
274+ #define EOF ((int)-1)
275+#endif
276+
277+
278+
279+// Summary: A structure containing information about the device.
280+// Description: The DISK structure contains information about the device being accessed.
281+typedef struct
282+{
283+ BYTE * buffer; // Address of the global data buffer used to read and write file information
284+ DWORD firsts; // Logical block address of the first sector of the FAT partition on the device
285+ DWORD fat; // Logical block address of the FAT
286+ DWORD root; // Logical block address of the root directory
287+ DWORD data; // Logical block address of the data section of the device.
288+ WORD maxroot; // The maximum number of entries in the root directory.
289+ DWORD maxcls; // The maximum number of clusters in the partition.
290+ DWORD sectorSize; // The size of a sector in bytes
291+ DWORD fatsize; // The number of sectors in the FAT
292+ BYTE fatcopy; // The number of copies of the FAT in the partition
293+ BYTE SecPerClus; // The number of sectors per cluster in the data region
294+ BYTE type; // The file system type of the partition (FAT12, FAT16 or FAT32)
295+ BYTE mount; // Device mount flag (TRUE if disk was mounted successfully, FALSE otherwise)
296+#if defined __PIC32MX__ || defined __C30__
297+} __attribute__ ((packed)) DISK;
298+#else
299+} DISK;
300+#endif
301+
302+
303+#ifdef __18CXX
304+ // Summary: A 24-bit data type
305+ // Description: The SWORD macro is used to defined a 24-bit data type. For 16+ bit architectures, this must be represented as
306+ // an array of three bytes.
307+ typedef unsigned short long SWORD;
308+#else
309+ // Summary: A 24-bit data type
310+ // Description: The SWORD macro is used to defined a 24-bit data type. For 16+ bit architectures, this must be represented as
311+ // an array of three bytes.
312+ typedef struct
313+ {
314+ unsigned char array[3];
315+#if defined __PIC32MX__ || defined __C30__
316+ } __attribute__ ((packed)) SWORD;
317+#else
318+ } SWORD;
319+#endif
320+#endif
321+
322+
323+
324+// Summary: A structure containing the bios parameter block for a FAT12 file system (in the boot sector)
325+// Description: The _BPB_FAT12 structure provides a layout of the "bios parameter block" in the boot sector of a FAT12 partition.
326+typedef struct {
327+ SWORD BootSec_JumpCmd; // Jump Command
328+ BYTE BootSec_OEMName[8]; // OEM name
329+ WORD BootSec_BPS; // Number of bytes per sector
330+ BYTE BootSec_SPC; // Number of sectors per cluster
331+ WORD BootSec_ResrvSec; // Number of reserved sectors at the beginning of the partition
332+ BYTE BootSec_FATCount; // Number of FATs on the partition
333+ WORD BootSec_RootDirEnts; // Number of root directory entries
334+ WORD BootSec_TotSec16; // Total number of sectors
335+ BYTE BootSec_MDesc; // Media descriptor
336+ WORD BootSec_SPF; // Number of sectors per FAT
337+ WORD BootSec_SPT; // Number of sectors per track
338+ WORD BootSec_HeadCnt; // Number of heads
339+ DWORD BootSec_HiddenSecCnt; // Number of hidden sectors
340+ DWORD BootSec_Reserved; // Reserved space
341+ BYTE BootSec_DriveNum; // Drive number
342+ BYTE BootSec_Reserved2; // Reserved space
343+ BYTE BootSec_BootSig; // Boot signature - equal to 0x29
344+ BYTE BootSec_VolID[4]; // Volume ID
345+ BYTE BootSec_VolLabel[11]; // Volume Label
346+ BYTE BootSec_FSType[8]; // File system type in ASCII. Not used for determination
347+#if defined __PIC32MX__ || defined __C30__
348+ } __attribute__ ((packed)) _BPB_FAT12;
349+#else
350+ } _BPB_FAT12;
351+#endif
352+
353+// Summary: A structure containing the bios parameter block for a FAT16 file system (in the boot sector)
354+// Description: The _BPB_FAT16 structure provides a layout of the "bios parameter block" in the boot sector of a FAT16 partition.
355+typedef struct {
356+ SWORD BootSec_JumpCmd; // Jump Command
357+ BYTE BootSec_OEMName[8]; // OEM name
358+ WORD BootSec_BPS; // Number of bytes per sector
359+ BYTE BootSec_SPC; // Number of sectors per cluster
360+ WORD BootSec_ResrvSec; // Number of reserved sectors at the beginning of the partition
361+ BYTE BootSec_FATCount; // Number of FATs on the partition
362+ WORD BootSec_RootDirEnts; // Number of root directory entries
363+ WORD BootSec_TotSec16; // Total number of sectors
364+ BYTE BootSec_MDesc; // Media descriptor
365+ WORD BootSec_SPF; // Number of sectors per FAT
366+ WORD BootSec_SPT; // Number of sectors per track
367+ WORD BootSec_HeadCnt; // Number of heads
368+ DWORD BootSec_HiddenSecCnt; // Number of hidden sectors
369+ DWORD BootSec_TotSec32; // Total sector count (32 bits)
370+ BYTE BootSec_DriveNum; // Drive number
371+ BYTE BootSec_Reserved; // Reserved space
372+ BYTE BootSec_BootSig; // Boot signature - equal to 0x29
373+ BYTE BootSec_VolID[4]; // Volume ID
374+ BYTE BootSec_VolLabel[11]; // Volume Label
375+ BYTE BootSec_FSType[8]; // File system type in ASCII. Not used for determination
376+#if defined __PIC32MX__ || defined __C30__
377+ } __attribute__ ((packed)) _BPB_FAT16;
378+#else
379+ } _BPB_FAT16;
380+#endif
381+
382+// Summary: A structure containing the bios parameter block for a FAT32 file system (in the boot sector)
383+// Description: The _BPB_FAT32 structure provides a layout of the "bios parameter block" in the boot sector of a FAT32 partition.
384+typedef struct {
385+ SWORD BootSec_jmpBoot; // Jump Command
386+ BYTE BootSec_OEMName[8]; // OEM name
387+ WORD BootSec_BytsPerSec; // Number of bytes per sector
388+ BYTE BootSec_SecPerClus; // Number of sectors per cluster
389+ WORD BootSec_RsvdSecCnt; // Number of reserved sectors at the beginning of the partition
390+ BYTE BootSec_NumFATs; // Number of FATs on the partition
391+ WORD BootSec_RootEntCnt; // Number of root directory entries
392+ WORD BootSec_TotSec16; // Total number of sectors
393+ BYTE BootSec_Media; // Media descriptor
394+ WORD BootSec_FATSz16; // Number of sectors per FAT
395+ WORD BootSec_SecPerTrk; // Number of sectors per track
396+ WORD BootSec_NumHeads; // Number of heads
397+ DWORD BootSec_HiddSec; // Number of hidden sectors
398+ DWORD BootSec_TotSec32; // Total sector count (32 bits)
399+ DWORD BootSec_FATSz32; // Sectors per FAT (32 bits)
400+ WORD BootSec_ExtFlags; // Presently active FAT. Defined by bits 0-3 if bit 7 is 1.
401+ WORD BootSec_FSVers; // FAT32 filesystem version. Should be 0:0
402+ DWORD BootSec_RootClus; // Start cluster of the root directory (should be 2)
403+ WORD BootSec_FSInfo; // File system information
404+ WORD BootSec_BkBootSec; // Backup boot sector address.
405+ BYTE BootSec_Reserved[12]; // Reserved space
406+ BYTE BootSec_DrvNum; // Drive number
407+ BYTE BootSec_Reserved1; // Reserved space
408+ BYTE BootSec_BootSig; // Boot signature - 0x29
409+ BYTE BootSec_VolID[4]; // Volume ID
410+ BYTE BootSec_VolLab[11]; // Volume Label
411+ BYTE BootSec_FilSysType[8]; // File system type in ASCII. Not used for determination
412+#if defined __PIC32MX__ || defined __C30__
413+ } __attribute__ ((packed)) _BPB_FAT32;
414+#else
415+ } _BPB_FAT32;
416+#endif
417+
418+
419+// Description: A macro for the boot sector bytes per sector value offset
420+#define BSI_BPS 11
421+
422+// Description: A macro for the boot sector sector per cluster value offset
423+#define BSI_SPC 13
424+
425+// Description: A macro for the boot sector reserved sector count value offset
426+#define BSI_RESRVSEC 14
427+
428+// Description: A macro for the boot sector FAT count value offset
429+#define BSI_FATCOUNT 16
430+
431+// Description: A macro for the boot sector root directory entry count value offset
432+#define BSI_ROOTDIRENTS 17
433+
434+// Description: A macro for the boot sector 16-bit total sector count value offset
435+#define BSI_TOTSEC16 19
436+
437+// Description: A macro for the boot sector sectors per FAT value offset
438+#define BSI_SPF 22
439+
440+// Description: A macro for the boot sector 32-bit total sector count value offset
441+#define BSI_TOTSEC32 32
442+
443+// Description: A macro for the boot sector boot signature offset
444+#define BSI_BOOTSIG 38
445+
446+// Description: A macro for the boot sector file system type string offset
447+#define BSI_FSTYPE 54
448+
449+// Description: A macro for the boot sector 32-bit sector per FAT value offset
450+#define BSI_FATSZ32 36
451+
452+// Description: A macro for the boot sector start cluster of root directory value offset
453+#define BSI_ROOTCLUS 44
454+
455+// Description: A macro for the FAT32 boot sector boot signature offset
456+#define BSI_FAT32_BOOTSIG 66
457+
458+// Description: A macro for the FAT32 boot sector file system type string offset
459+#define BSI_FAT32_FSTYPE 82
460+
461+
462+
463+// Summary: A partition table entry structure.
464+// Description: The PTE_MBR structure contains values found in a partition table entry in the MBR of a device.
465+typedef struct
466+{
467+ BYTE PTE_BootDes; // The boot descriptor (should be 0x00 in a non-bootable device)
468+ SWORD PTE_FrstPartSect; // The cylinder-head-sector address of the first sector of the partition
469+ BYTE PTE_FSDesc; // The file system descriptor
470+ SWORD PTE_LstPartSect; // The cylinder-head-sector address of the last sector of the partition
471+ DWORD PTE_FrstSect; // The logical block address of the first sector of the partition
472+ DWORD PTE_NumSect; // The number of sectors in a partition
473+#if defined __PIC32MX__ || defined __C30__
474+ } __attribute__ ((packed)) PTE_MBR;
475+#else
476+ } PTE_MBR;
477+#endif
478+
479+
480+// Summary: A structure of the organization of a master boot record.
481+// Description: The _PT_MBR structure has the same form as a master boot record. When the MBR is loaded from the device, it will
482+// be cast as a _PT_MBR structure so the MBR elements can be accessed.
483+typedef struct
484+{
485+ BYTE ConsChkRtn[446]; // Boot code
486+ PTE_MBR Partition0; // The first partition table entry
487+ PTE_MBR Partition1; // The second partition table entry
488+ PTE_MBR Partition2; // The third partition table entry
489+ PTE_MBR Partition3; // The fourth partition table entry
490+ BYTE Signature0; // MBR signature code - equal to 0x55
491+ BYTE Signature1; // MBR signature code - equal to 0xAA
492+#if defined __PIC32MX__ || defined __C30__
493+}__attribute__((packed)) _PT_MBR;
494+#else
495+}_PT_MBR;
496+#endif
497+
498+// Summary: A pointer to a _PT_MBR structure
499+// Description: The PT_MBR pointer points to a _PT_MBR structure.
500+typedef _PT_MBR * PT_MBR;
501+
502+
503+
504+// Summary: A structure of the organization of a boot sector.
505+// Description: The _BootSec structure has the same form as a boot sector. When the boot sector is loaded from the device, it will
506+// be cast as a _BootSec structure so the boot sector elements can be accessed.
507+typedef struct
508+{
509+ // A union of different bios parameter blocks
510+ union
511+ {
512+ _BPB_FAT32 FAT_32;
513+ _BPB_FAT16 FAT_16;
514+ _BPB_FAT12 FAT_12;
515+ }FAT;
516+ BYTE Reserved[512-sizeof(_BPB_FAT32)-2]; // Reserved space
517+ BYTE Signature0; // Boot sector signature code - equal to 0x55
518+ BYTE Signature1; // Boot sector signature code - equal to 0xAA
519+#if defined __PIC32MX__ || defined __C30__
520+ } __attribute__ ((packed)) _BootSec;
521+#else
522+ } _BootSec;
523+#endif
524+
525+// Summary: A pointer to a _BootSec structure
526+// Description: The BootSec pointer points to a _BootSec structure.
527+typedef _BootSec * BootSec;
528+
529+
530+
531+// Summary: A macro indicating the offset for the master boot record
532+// Description: FO_MBR is a macro that indicates the addresss of the master boot record on the device. When the device is initialized
533+// this sector will be read
534+#define FO_MBR 0L
535+
536+
537+
538+// Summary: A macro for the first boot sector/MBR signature byte
539+// Description: The FAT_GOOD_SIGN_0 macro is used to determine that the first byte of the MBR or boot sector signature code is correct
540+#define FAT_GOOD_SIGN_0 0x55
541+
542+// Summary: A macro for the second boot sector/MBR signature byte
543+// Description: The FAT_GOOD_SIGN_1 macro is used to determine that the second byte of the MBR or boot sector signature code is correct
544+#define FAT_GOOD_SIGN_1 0xAA
545+
546+
547+typedef struct
548+{
549+ BYTE errorCode;
550+ union
551+ {
552+ BYTE value;
553+ struct
554+ {
555+ BYTE sectorSize : 1;
556+ BYTE maxLUN : 1;
557+ } bits;
558+ } validityFlags;
559+
560+ WORD sectorSize;
561+ BYTE maxLUN;
562+} MEDIA_INFORMATION;
563+
564+typedef enum
565+{
566+ MEDIA_NO_ERROR, // No errors
567+ MEDIA_DEVICE_NOT_PRESENT, // The requested device is not present
568+ MEDIA_CANNOT_INITIALIZE // Cannot initialize media
569+} MEDIA_ERRORS;
570+
571+
572+/*******************************************************************/
573+/* Strunctures and defines */
574+/*******************************************************************/
575+
576+#ifndef FALSE
577+ // Summary: False value
578+ // Description: This macro will indicate that a condition is false.
579+ #define FALSE 0
580+#endif
581+#ifndef TRUE
582+ // Summary: True value
583+ // Description: This macro will indicate that a condition is true.
584+ #define TRUE !FALSE // True value
585+#endif
586+
587+
588+
589+
590+#ifndef SEEK_SET
591+ // Summary: Macro for the FSfseek SEEK_SET base location.
592+ // Description: Functions as an input for FSfseek that specifies that the position in the file will be changed
593+ // relative to the beginning of the file.
594+ #define SEEK_SET 0
595+
596+#endif
597+#ifndef SEEK_CUR
598+
599+ // Summary: Macro for the FSfseek SEEK_CUR base location.
600+ // Description: Functions as an input for FSfseek that specifies that the position in the file will be changed
601+ // relative to the current location of the file
602+ #define SEEK_CUR 1
603+
604+#endif
605+#ifndef SEEK_END
606+
607+ // Summary: Macro for the FSfseek SEEK_END base location
608+ // Description: Functions as an input for FSfseek that specifies that the position in the file will be changed
609+ // relative to the end of the file. For this macro, the offset value will be subtracted from
610+ // the end location of the file by default.
611+ #define SEEK_END 2
612+
613+#endif
614+
615+
616+
617+
618+// Summary: Macro for the FSfopen FS_APPEND mode
619+// Description: If this macro is specified as the mode argument in a call of FSfopen, the file being opened will
620+// be created if it doesn't exist. If it does exist, it's file information will be loaded and the
621+// current location in the file will be set to the end. The user will then be able to write to the file.
622+#define FS_APPEND "a"
623+#define APPEND "a" //deprecated
624+
625+// Summary: Macro for the FSfopen FS_WRITE mode
626+// Description: If this macro is specified as the mode argument in a call of FSfopen, the file being opened will
627+// be created if it doesn't exist. If it does exist, it will be erased and replaced by an empty file
628+// of the same name. The user will then be able to write to the file.
629+#define FS_WRITE "w"
630+#define WRITE "w" //deprecated
631+
632+// Summary: Macro for the FSfopen FS_READ mode
633+// Description: If this macro is specified as the mode argument in a call of FSfopen, the file information for the
634+// specified file will be loaded. If the file does not exist, the FSfopen function will fail. The user
635+// will then be able to read from the file.
636+#define FS_READ "r"
637+#if defined(__32MX795F512L__)
638+// #warning FSfopen must use "r" and not READ as input on this device
639+#else
640+ #define READ "r" //deprecated
641+#endif
642+
643+// Summary: Macro for the FSfopen FS_APPEND+ mode
644+// Description: If this macro is specified as the mode argument in a call of FSfopen, the file being opened will
645+// be created if it doesn't exist. If it does exist, it's file information will be loaded and the
646+// current location in the file will be set to the end. The user will then be able to write to the file
647+// or read from the file.
648+#define FS_APPENDPLUS "a+"
649+#define APPENDPLUS "a+" //deprecated
650+
651+// Summary: Macro for the FSfopen FS_WRITE+ mode
652+// Description: If this macro is specified as the mode argument in a call of FSfopen, the file being opened will
653+// be created if it doesn't exist. If it does exist, it will be erased and replaced by an empty file
654+// of the same name. The user will then be able to write to the file or read from the file.
655+#define FS_WRITEPLUS "w+"
656+#define WRITEPLUS "w+" //deprecated
657+
658+// Summary: Macro for the FSfopen FS_READ+ mode
659+// Description: If this macro is specified as the mode argument in a call of FSfopen, the file information for the
660+// specified file will be loaded. If the file does not exist, the FSfopen function will fail. The user
661+// will then be able to read from the file or write to the file.
662+#define FS_READPLUS "r+"
663+#define READPLUS "r+" //deprecated
664+
665+
666+
667+#ifndef intmax_t
668+ #ifdef __PIC24F__
669+ // Summary: A data type indicating the maximum integer size in an architecture
670+ // Description: The intmax_t data type refers to the maximum-sized data type on any given architecture. This
671+ // data type can be specified as a format specifier size specification for the FSfprintf function.
672+ #define intmax_t long long
673+ #elif defined __PIC24H__
674+ #define intmax_t long long
675+ #elif defined __dsPIC30F__
676+ #define intmax_t long long
677+ #elif defined __dsPIC33F__
678+ #define intmax_t long long
679+ #endif
680+#endif
681+
682+
683+
684+// Summary: Indicates flag conditions for a file object
685+// Description: The FILEFLAGS structure is used to indicate conditions in a file. It contains three flags: 'write' indicates
686+// that the file was opened in a mode that allows writes, 'read' indicates that the file was opened in a mode
687+// that allows reads, and 'FileWriteEOF' indicates that additional data that is written to the file will increase
688+// the file size.
689+typedef struct
690+{
691+ unsigned write :1; // Indicates a file was opened in a mode that allows writes
692+ unsigned read :1; // Indicates a file was opened in a mode that allows reads
693+ unsigned FileWriteEOF :1; // Indicates the current position in a file is at the end of the file
694+}FILEFLAGS;
695+
696+
697+
698+// Summary: Indicates how to search for file entries in the FILEfind function
699+// Description: The values in the SEARCH_TYPE enumeration are used internally by the library to indicate how the FILEfind function
700+// how to perform a search. The 'LOOK_FOR_EMPTY_ENTRY' value indicates that FILEfind should search for an empty file entry.
701+// The 'LOOK_FOR_MATCHING_ENTRY' value indicates that FILEfind should search for an entry that matches the FSFILE object
702+// that was passed into the FILEfind function.
703+typedef enum{
704+ LOOK_FOR_EMPTY_ENTRY = 0,
705+ LOOK_FOR_MATCHING_ENTRY
706+} SEARCH_TYPE;
707+
708+
709+
710+// Summary: Macro indicating the length of a 8.3 file name
711+// Description: The TOTAL_FILE_SIZE_8P3 macro indicates the maximum number of characters in an 8.3 file name. This value includes
712+// 8 characters for the name, three for the extentsion, and 1 for the radix ('.')
713+#define TOTAL_FILE_SIZE_8P3 (8+3+1)
714+#define TOTAL_FILE_SIZE TOTAL_FILE_SIZE_8P3
715+
716+// Summary: Macro indicating the max length of a LFN file name
717+// Description: The MAX_FILE_NAME_LENGTH_LFN macro indicates the maximum number of characters in an LFN file name.
718+#define MAX_FILE_NAME_LENGTH_LFN 256
719+
720+// Summary: A mask that indicates the limit of directory entries in a sector
721+// Description: The MASK_MAX_FILE_ENTRY_LIMIT_BITS is used to indicate to the Cache_File_Entry function that a new sector needs to
722+// be loaded.
723+#define MASK_MAX_FILE_ENTRY_LIMIT_BITS 0x0f
724+
725+// Summary: Value used for shift operations to calculate the sector offset in a directory
726+// Description: The VALUE_BASED_ON_ENTRIES_PER_CLUSTER macro is used to calculate sector offsets for directories. The position of the
727+// entry is shifted by 4 bits (divided by 16, since there are 16 entries in a sector) to calculate how many sectors a
728+// specified entry is offset from the beginning of the directory.
729+#define VALUE_BASED_ON_ENTRIES_PER_CLUSTER 4
730+
731+// Summary: A value that will indicate that a dotdot directory entry points to the root.
732+// Description: The VALUE_DOTDOT_CLUSTER_VALUE_FOR_ROOT macro is used as an absolute address when writing information to a dotdot entry
733+// in a newly created directory. If a dotdot entry points to the root directory, it's cluster value must be set to 0,
734+// regardless of the actual cluster number of the root directory.
735+#define VALUE_DOTDOT_CLUSTER_VALUE_FOR_ROOT 0
736+
737+// Summary: MAcro indicating the length of an 8.3 file name in a directory entry
738+// Description: The FILE_NAME_SIZE_8P3 macro indicates the number of characters that an 8.3 file name will take up when packed in
739+// a directory entry. This value includes 8 characters for the name and 3 for the extension. Note that the radix is not
740+// stored in the directory entry.
741+#define FILE_NAME_SIZE_8P3 11
742+#define FILE_NAME_SIZE FILE_NAME_SIZE_8P3
743+
744+
745+// Summary: Contains file information and is used to indicate which file to access.
746+// Description: The FSFILE structure is used to hold file information for an open file as it's being modified or accessed. A pointer to
747+// an open file's FSFILE structure will be passeed to any library function that will modify that file.
748+typedef struct
749+{
750+ DISK * dsk; // Pointer to a DISK structure
751+ DWORD cluster; // The first cluster of the file
752+ DWORD ccls; // The current cluster of the file
753+ WORD sec; // The current sector in the current cluster of the file
754+ WORD pos; // The position in the current sector
755+ DWORD seek; // The absolute position in the file
756+ DWORD size; // The size of the file
757+ FILEFLAGS flags; // A structure containing file flags
758+ WORD time; // The file's last update time
759+ WORD date; // The file's last update date
760+ char name[FILE_NAME_SIZE_8P3]; // The short name of the file
761+ #ifdef SUPPORT_LFN
762+ BOOL AsciiEncodingType; // Ascii file name or Non-Ascii file name indicator
763+ unsigned short int *utf16LFNptr; // Pointer to long file name in UTF16 format
764+ unsigned short int utf16LFNlength; // LFN length in terms of words including the NULL word at the last.
765+ #endif
766+ WORD entry; // The position of the file's directory entry in it's directory
767+ WORD chk; // File structure checksum
768+ WORD attributes; // The file attributes
769+ DWORD dirclus; // The base cluster of the file's directory
770+ DWORD dirccls; // The current cluster of the file's directory
771+} FSFILE;
772+
773+/* Summary: Possible results of the FSGetDiskProperties() function.
774+** Description: See the FSGetDiskProperties() function for more information.
775+*/
776+typedef enum
777+{
778+ FS_GET_PROPERTIES_NO_ERRORS = 0,
779+ FS_GET_PROPERTIES_DISK_NOT_MOUNTED,
780+ FS_GET_PROPERTIES_CLUSTER_FAILURE,
781+ FS_GET_PROPERTIES_STILL_WORKING = 0xFF
782+} FS_DISK_ERRORS;
783+
784+
785+/* Summary: Contains the disk search information, intermediate values, and results
786+** Description: This structure is used in conjunction with the FSGetDiskProperties()
787+** function. See that function for more information about the usage.
788+*/
789+typedef struct
790+{
791+ DISK * disk; /* pointer to the disk we are searching */
792+ BOOL new_request; /* is this a new request or a continued request */
793+ FS_DISK_ERRORS properties_status; /* status of the last call of the function */
794+
795+ struct
796+ {
797+ BYTE disk_format; /* disk format: FAT12, FAT16, FAT32 */
798+ WORD sector_size; /* sector size of the drive */
799+ BYTE sectors_per_cluster; /* number of sectors per cluster */
800+ DWORD total_clusters; /* the number of total clusters on the drive */
801+ DWORD free_clusters; /* the number of free (unused) clusters on drive */
802+ } results; /* the results of the current search */
803+
804+ struct
805+ {
806+ DWORD c;
807+ DWORD curcls;
808+ DWORD EndClusterLimit;
809+ DWORD ClusterFailValue;
810+ } private; /* intermediate values used to continue searches. This
811+ member should be used only by the FSGetDiskProperties()
812+ function */
813+
814+} FS_DISK_PROPERTIES;
815+
816+// Summary: A structure used for searching for files on a device.
817+// Description: The SearchRec structure is used when searching for file on a device. It contains parameters that will be loaded with
818+// file information when a file is found. It also contains the parameters that the user searched for, allowing further
819+// searches to be perfomed in the same directory for additional files that meet the specified criteria.
820+typedef struct
821+{
822+ char filename[FILE_NAME_SIZE_8P3 + 2]; // The name of the file that has been found
823+ unsigned char attributes; // The attributes of the file that has been found
824+ unsigned long filesize; // The size of the file that has been found
825+ unsigned long timestamp; // The last modified time of the file that has been found (create time for directories)
826+ #ifdef SUPPORT_LFN
827+ BOOL AsciiEncodingType; // Ascii file name or Non-Ascii file name indicator
828+ unsigned short int *utf16LFNfound; // Pointer to long file name found in UTF16 format
829+ unsigned short int utf16LFNfoundLength; // LFN Found length in terms of words including the NULL word at the last.
830+ #endif
831+ unsigned int entry; // The directory entry of the last file found that matches the specified attributes. (Internal use only)
832+ char searchname[FILE_NAME_SIZE_8P3 + 2]; // The 8.3 format name specified when the user began the search. (Internal use only)
833+ unsigned char searchattr; // The attributes specified when the user began the search. (Internal use only)
834+ unsigned long cwdclus; // The directory that this search was performed in. (Internal use only)
835+ unsigned char initialized; // Check to determine if the structure was initialized by FindFirst (Internal use only)
836+} SearchRec;
837+
838+
839+/***************************************************************************
840+* Prototypes *
841+***************************************************************************/
842+
843+
844+
845+
846+/*************************************************************************
847+ Function:
848+ int FSInit(void)
849+ Summary:
850+ Function to initialize the device.
851+ Conditions:
852+ The physical device should be connected to the microcontroller.
853+ Input:
854+ None
855+ Return Values:
856+ TRUE - Initialization successful
857+ FALSE - Initialization unsuccessful
858+ Side Effects:
859+ The FSerrno variable will be changed.
860+ Description:
861+ Initializes the static or dynamic memory slots for holding file
862+ structures. Initializes the device with the DISKmount function. Loads
863+ MBR and boot sector information. Initializes the current working
864+ directory to the root directory for the device if directory support
865+ is enabled.
866+ Remarks:
867+ None
868+ *************************************************************************/
869+
870+int FSInit(void);
871+
872+
873+/*********************************************************************
874+ Function:
875+ FSFILE * FSfopen (const char * fileName, const char *mode)
876+ Summary:
877+ Open a Ascii file
878+ Conditions:
879+ For read modes, file exists; FSInit performed
880+ Input:
881+ fileName - The name of the file to open
882+ mode -
883+ - WRITE - Create a new file or replace an existing file
884+ - READ - Read data from an existing file
885+ - APPEND - Append data to an existing file
886+ - WRITEPLUS - Create a new file or replace an existing file (reads also enabled)
887+ - READPLUS - Read data from an existing file (writes also enabled)
888+ - APPENDPLUS - Append data to an existing file (reads also enabled)
889+ Return Values:
890+ FSFILE * - The pointer to the file object
891+ NULL - The file could not be opened
892+ Side Effects:
893+ The FSerrno variable will be changed.
894+ Description:
895+ This function will open a file or directory. First, RAM in the
896+ dynamic heap or static array will be allocated to a new FSFILE object.
897+ Then, the specified file name will be formatted to ensure that it's
898+ in 8.3 format or LFN format. Next, the FILEfind function will be used
899+ to search for the specified file name. If the name is found, one of three
900+ things will happen: if the file was opened in read mode, its file
901+ info will be loaded using the FILEopen function; if it was opened in
902+ write mode, it will be erased, and a new file will be constructed in
903+ its place; if it was opened in append mode, its file info will be
904+ loaded with FILEopen and the current location will be moved to the
905+ end of the file using the FSfseek function. If the file was not
906+ found by FILEfind, a new file will be created if the mode was specified as
907+ a write or append mode. In these cases, a pointer to the heap or
908+ static FSFILE object array will be returned. If the file was not
909+ found and the mode was specified as a read mode, the memory
910+ allocated to the file will be freed and the NULL pointer value
911+ will be returned.
912+ Remarks:
913+ None.
914+ *********************************************************************/
915+
916+FSFILE * FSfopen(const char * fileName, const char *mode);
917+
918+#ifdef SUPPORT_LFN
919+/*********************************************************************
920+ Function:
921+ FSFILE * wFSfopen (const unsigned short int * fileName, const char *mode)
922+ Summary:
923+ Open a UTF16 file.
924+ Conditions:
925+ For read modes, file exists; FSInit performed
926+ Input:
927+ fileName - The name of the file to open
928+ mode -
929+ - WRITE - Create a new file or replace an existing file
930+ - READ - Read data from an existing file
931+ - APPEND - Append data to an existing file
932+ - WRITEPLUS - Create a new file or replace an existing file (reads also enabled)
933+ - READPLUS - Read data from an existing file (writes also enabled)
934+ - APPENDPLUS - Append data to an existing file (reads also enabled)
935+ Return Values:
936+ FSFILE * - The pointer to the file object
937+ NULL - The file could not be opened
938+ Side Effects:
939+ The FSerrno variable will be changed.
940+ Description:
941+ This function will open a file or directory. First, RAM in the
942+ dynamic heap or static array will be allocated to a new FSFILE object.
943+ Then, the specified file name will be formatted to ensure that it's
944+ in 8.3 format or LFN format. Next, the FILEfind function will be used
945+ to search for the specified file name. If the name is found, one of three
946+ things will happen: if the file was opened in read mode, its file
947+ info will be loaded using the FILEopen function; if it was opened in
948+ write mode, it will be erased, and a new file will be constructed in
949+ its place; if it was opened in append mode, its file info will be
950+ loaded with FILEopen and the current location will be moved to the
951+ end of the file using the FSfseek function. If the file was not
952+ found by FILEfind, a new file will be created if the mode was specified as
953+ a write or append mode. In these cases, a pointer to the heap or
954+ static FSFILE object array will be returned. If the file was not
955+ found and the mode was specified as a read mode, the memory
956+ allocated to the file will be freed and the NULL pointer value
957+ will be returned.
958+ Remarks:
959+ None.
960+ *********************************************************************/
961+
962+FSFILE * wFSfopen(const unsigned short int * fileName, const char *mode);
963+#endif
964+
965+#ifdef ALLOW_PGMFUNCTIONS
966+
967+/******************************************************************************
968+ Function:
969+ FSFILE * FSfopenpgm(const rom char * fileName, const rom char *mode)
970+ Summary:
971+ Open a Ascii file named with a ROM string on PIC18
972+ Conditions:
973+ For read modes, file exists; FSInit performed
974+ Input:
975+ fileName - The name of the file to be opened (ROM)
976+ mode - The mode the file will be opened in (ROM)
977+ Return Values:
978+ FSFILE * - A pointer to the file object
979+ NULL - File could not be opened
980+ Side Effects:
981+ The FSerrno variable will be changed.
982+ Description:
983+ The FSfopenpgm function will copy a PIC18 ROM fileName and mode argument
984+ into RAM arrays, and then pass those arrays to the FSfopen function.
985+ Remarks:
986+ This function is for use with PIC18 when passing arguments in ROM.
987+ ******************************************************************************/
988+
989+ FSFILE * FSfopenpgm(const rom char * fileName, const rom char *mode);
990+
991+
992+/**************************************************************************************
993+ Function:
994+ int FindFirstpgm (const char * fileName, unsigned int attr, SearchRec * rec)
995+ Summary:
996+ Find a file named with a ROM string on PIC18
997+ Conditions:
998+ None
999+ Input:
1000+ fileName - The name of the file to be found (ROM)
1001+ attr - The attributes of the file to be found
1002+ rec - Pointer to a search record to store the file info in
1003+ Return Values:
1004+ 0 - File was found
1005+ -1 - No file matching the given parameters was found
1006+ Side Effects:
1007+ Search criteria from previous FindFirstpgm call on passed SearchRec object
1008+ will be lost.The FSerrno variable will be changed.
1009+ Description:
1010+ The FindFirstpgm function will copy a PIC18 ROM fileName argument
1011+ into a RAM array, and then pass that array to the FindFirst function.
1012+ Remarks:
1013+ Call FindFirstpgm or FindFirst before calling FindNext.
1014+ This function is for use with PIC18 when passing arguments in ROM.
1015+ **************************************************************************************/
1016+
1017+ int FindFirstpgm (const rom char * fileName, unsigned int attr, SearchRec * rec);
1018+
1019+
1020+/**************************************************************************
1021+ Function:
1022+ int FSchdirpgm (const rom char * path)
1023+ Summary:
1024+ Changed the CWD with a path in ROM on PIC18
1025+ Conditions:
1026+ None
1027+ Input:
1028+ path - The path of the directory to change to (ROM)
1029+ Return Values:
1030+ 0 - The current working directory was changed successfully
1031+ EOF - The current working directory could not be changed
1032+ Side Effects:
1033+ The current working directory may be changed. The FSerrno variable will
1034+ be changed.
1035+ Description:
1036+ The FSchdirpgm function passes a PIC18 ROM path pointer to the
1037+ chdirhelper function.
1038+ Remarks:
1039+ This function is for use with PIC18 when passing arguments in ROM
1040+ **************************************************************************/
1041+
1042+ int FSchdirpgm (const rom char * path);
1043+
1044+ #ifdef ALLOW_WRITES
1045+
1046+
1047+/*************************************************************
1048+ Function:
1049+ int FSremovepgm (const rom char * fileName)
1050+ Summary:
1051+ Delete a file named with a ROM string on PIC18
1052+ Conditions:
1053+ File not opened; file exists
1054+ Input:
1055+ fileName - The name of the file to be deleted (ROM)
1056+ Return Values:
1057+ 0 - File was removed successfully
1058+ -1 - File could not be removed
1059+ Side Effects:
1060+ The FSerrno variable will be changed.
1061+ Description:
1062+ The FSremovepgm function will copy a PIC18 ROM fileName argument
1063+ into a RAM array, and then pass that array to the FSremove function.
1064+ Remarks:
1065+ This function is for use with PIC18 when passing arguments in ROM.
1066+ *************************************************************/
1067+
1068+ int FSremovepgm (const rom char * fileName);
1069+
1070+
1071+/**************************************************************************
1072+ Function:
1073+ int FSmkdirpgm (const rom char * path)
1074+ Summary:
1075+ Create a directory with a path in ROM on PIC18
1076+ Conditions:
1077+ None
1078+ Input:
1079+ path - The path of directories to create (ROM)
1080+ Return Values:
1081+ 0 - The specified directory was created successfully
1082+ EOF - The specified directory could not be created
1083+ Side Effects:
1084+ Will create all non-existent directories in the path. The FSerrno
1085+ variable will be changed.
1086+ Description:
1087+ The FSmkdirpgm function passes a PIC18 ROM path pointer to the
1088+ mkdirhelper function.
1089+ Remarks:
1090+ This function is for use with PIC18 when passing arugments in ROM
1091+ **************************************************************************/
1092+
1093+ int FSmkdirpgm (const rom char * path);
1094+
1095+
1096+/**************************************************************************
1097+ Function:
1098+ int FSrmdirpgm (const rom char * path)
1099+ Summary:
1100+ Delete a directory with a path in ROM on PIC18
1101+ Conditions:
1102+ None.
1103+ Input:
1104+ path - The path of the directory to remove (ROM)
1105+ rmsubdirs -
1106+ - TRUE - All sub-dirs and files in the target dir will be removed
1107+ - FALSE - FSrmdir will not remove non-empty directories
1108+ Return Values:
1109+ 0 - The specified directory was deleted successfully
1110+ EOF - The specified directory could not be deleted
1111+ Side Effects:
1112+ The FSerrno variable will be changed.
1113+ Description:
1114+ The FSrmdirpgm function passes a PIC18 ROM path pointer to the
1115+ rmdirhelper function.
1116+ Remarks:
1117+ This function is for use with PIC18 when passing arguments in ROM.
1118+ **************************************************************************/
1119+
1120+ int FSrmdirpgm (const rom char * path, unsigned char rmsubdirs);
1121+
1122+
1123+/*****************************************************************
1124+ Function:
1125+ int FSrenamepgm(const rom char * fileName, FSFILE * fo)
1126+ Summary:
1127+ Rename a file named with a ROM string on PIC18
1128+ Conditions:
1129+ File opened.
1130+ Input:
1131+ fileName - The new name of the file (in ROM)
1132+ fo - The file to rename
1133+ Return Values:
1134+ 0 - File renamed successfully
1135+ -1 - File could not be renamed
1136+ Side Effects:
1137+ The FSerrno variable will be changed.
1138+ Description:
1139+ The Fsrenamepgm function will copy the rom fileName specified
1140+ by the user into a RAM array and pass that array into the
1141+ FSrename function.
1142+ Remarks:
1143+ This function is for use with PIC18 when passing arguments in ROM.
1144+ *****************************************************************/
1145+
1146+ int FSrenamepgm (const rom char * fileName, FSFILE * fo);
1147+ #endif
1148+#endif
1149+
1150+
1151+/************************************************************
1152+ Function:
1153+ int FSfclose(FSFILE *fo)
1154+ Summary:
1155+ Update file information and free FSFILE objects
1156+ Conditions:
1157+ File opened
1158+ Input:
1159+ fo - Pointer to the file to close
1160+ Return Values:
1161+ 0 - File closed successfully
1162+ EOF - Error closing the file
1163+ Side Effects:
1164+ The FSerrno variable will be changed.
1165+ Description:
1166+ This function will update the directory entry for the
1167+ file pointed to by 'fo' with the information contained
1168+ in 'fo,' including the new file size and attributes.
1169+ Timestamp information will also be loaded based on the
1170+ method selected by the user and written to the entry
1171+ as the last modified time and date. The file entry will
1172+ then be written to the device. Finally, the memory
1173+ used for the specified file object will be freed from
1174+ the dynamic heap or the array of FSFILE objects.
1175+ Remarks:
1176+ A function to flush data to the device without closing the
1177+ file can be created by removing the portion of this
1178+ function that frees the memory and the line that clears
1179+ the write flag.
1180+ ************************************************************/
1181+
1182+int FSfclose(FSFILE *fo);
1183+
1184+
1185+/*********************************************************
1186+ Function:
1187+ void FSrewind (FSFILE * fo)
1188+ Summary:
1189+ Set the current position in a file to the beginning
1190+ Conditions:
1191+ File opened.
1192+ Input:
1193+ fo - Pointer to file structure
1194+ Return Values:
1195+ None
1196+ Side Effects:
1197+ None.
1198+ Description:
1199+ The FSrewind funciton will reset the position of the
1200+ specified file to the beginning of the file. This
1201+ functionality is faster than using FSfseek to reset
1202+ the position in the file.
1203+ Remarks:
1204+ None.
1205+ *********************************************************/
1206+
1207+void FSrewind (FSFILE *fo);
1208+
1209+
1210+/**************************************************************************
1211+ Function:
1212+ size_t FSfread(void *ptr, size_t size, size_t n, FSFILE *stream)
1213+ Summary:
1214+ Read data from a file
1215+ Conditions:
1216+ File is opened in a read mode
1217+ Input:
1218+ ptr - Destination buffer for read bytes
1219+ size - Size of units in bytes
1220+ n - Number of units to be read
1221+ stream - File to be read from
1222+ Return:
1223+ size_t - number of units read
1224+ Side Effects:
1225+ The FSerrno variable will be changed.
1226+ Description:
1227+ The FSfread function will read data from the specified file. First,
1228+ the appropriate sector of the file is loaded. Then, data is read into
1229+ the specified buffer until the specified number of bytes have been read.
1230+ When a cluster boundary is reached, a new cluster will be loaded. The
1231+ parameters 'size' and 'n' indicate how much data to read. 'Size'
1232+ refers to the size of one object to read (in bytes), and 'n' will refer
1233+ to the number of these objects to read. The value returned will be equal
1234+ to 'n' unless an error occured or the user tried to read beyond the end
1235+ of the file.
1236+ Remarks:
1237+ None.
1238+ **************************************************************************/
1239+
1240+size_t FSfread(void *ptr, size_t size, size_t n, FSFILE *stream);
1241+
1242+
1243+/**********************************************************************
1244+ Function:
1245+ int FSfseek(FSFILE *stream, long offset, int whence)
1246+ Summary:
1247+ Change the current position in a file
1248+ Conditions:
1249+ File opened
1250+ Input:
1251+ stream - Pointer to file structure
1252+ offset - Offset from base location
1253+ whence -
1254+ - SEEK_SET - Seek from start of file
1255+ - SEEK_CUR - Seek from current location
1256+ - SEEK_END - Seek from end of file (subtract offset)
1257+ Return Values:
1258+ 0 - Operation successful
1259+ -1 - Operation unsuccesful
1260+ Side Effects:
1261+ The FSerrno variable will be changed.
1262+ Description:
1263+ The FSfseek function will change the current position in the file to
1264+ one specified by the user. First, an absolute offset is calculated
1265+ using the offset and base location passed in by the user. Then, the
1266+ position variables are updated, and the sector number that corresponds
1267+ to the new location. That sector is then loaded. If the offset
1268+ falls exactly on a cluster boundary, a new cluster will be allocated
1269+ to the file and the position will be set to the first byte of that
1270+ cluster.
1271+ Remarks:
1272+ None
1273+ **********************************************************************/
1274+
1275+int FSfseek(FSFILE *stream, long offset, int whence);
1276+
1277+
1278+/*******************************************************************
1279+ Function:
1280+ long FSftell (FSFILE * fo)
1281+ Summary:
1282+ Determine the current location in a file
1283+ Conditions:
1284+ File opened
1285+ Input:
1286+ fo - Pointer to file structure
1287+ Return: Current location in the file
1288+ Side Effects:
1289+ The FSerrno variable will be changed
1290+ Description:
1291+ The FSftell function will return the current position in the
1292+ file pointed to by 'fo' by returning the 'seek' variable in the
1293+ FSFILE object, which is used to keep track of the absolute
1294+ location of the current position in the file.
1295+ Remarks:
1296+ None
1297+ *******************************************************************/
1298+
1299+long FSftell(FSFILE *fo);
1300+
1301+
1302+/****************************************************
1303+ Function:
1304+ int FSfeof( FSFILE * stream )
1305+ Summary:
1306+ Indicate whether the current file position is at the end
1307+ Conditions:
1308+ File is open in a read mode
1309+ Input:
1310+ stream - Pointer to the target file
1311+ Return Values:
1312+ Non-Zero - EOF reached
1313+ 0 - Not at end of File
1314+ Side Effects:
1315+ The FSerrno variable will be changed.
1316+ Description:
1317+ The FSfeof function will indicate that the end-of-
1318+ file has been reached for the specified file by
1319+ comparing the absolute location in the file to the
1320+ size of the file.
1321+ Remarks:
1322+ None.
1323+ ****************************************************/
1324+
1325+int FSfeof( FSFILE * stream );
1326+
1327+
1328+#ifdef ALLOW_FORMATS
1329+/*******************************************************************
1330+ Function:
1331+ int FSformat (char mode, long int serialNumber, char * volumeID)
1332+ Summary:
1333+ Formats a device
1334+ Conditions:
1335+ The device must possess a valid master boot record.
1336+ Input:
1337+ mode - - 0 - Just erase the FAT and root
1338+ - 1 - Create a new boot sector
1339+ serialNumber - Serial number to write to the card
1340+ volumeID - Name of the card
1341+ Return Values:
1342+ 0 - Format was successful
1343+ EOF - Format was unsuccessful
1344+ Side Effects:
1345+ The FSerrno variable will be changed.
1346+ Description:
1347+ The FSformat function can be used to create a new boot sector
1348+ on a device, based on the information in the master boot record.
1349+ This function will first initialize the I/O pins and the device,
1350+ and then attempts to read the master boot record. If the MBR
1351+ cannot be loaded successfully, the function will fail. Next, if
1352+ the 'mode' argument is specified as '0' the existing boot sector
1353+ information will be loaded. If the 'mode' argument is '1' an
1354+ entirely new boot sector will be constructed using the disk
1355+ values from the master boot record. Once the boot sector has
1356+ been successfully loaded/created, the locations of the FAT and
1357+ root will be loaded from it, and they will be completely
1358+ erased. If the user has specified a volumeID parameter, a
1359+ VOLUME attribute entry will be created in the root directory
1360+ to name the device.
1361+
1362+ FAT12, FAT16 and FAT32 formatting are supported.
1363+
1364+ Based on the number of sectors, the format function automatically
1365+ compute the smallest possible value for the cluster size in order to
1366+ accommodate the physical size of the media. In this case, if a media
1367+ with a big capacity is formatted, the format function may take a very
1368+ long time to write all the FAT tables.
1369+
1370+ Therefore, the FORMAT_SECTORS_PER_CLUSTER macro may be used to
1371+ specify the exact cluster size (in multiples of sector size). This
1372+ macro can be defined in FSconfig.h
1373+
1374+ Remarks:
1375+ Only devices with a sector size of 512 bytes are supported by the
1376+ format function
1377+ *******************************************************************/
1378+
1379+int FSformat (char mode, long int serialNumber, char * volumeID);
1380+#endif
1381+
1382+
1383+#ifdef ALLOW_WRITES
1384+/***************************************************************************
1385+ Function:
1386+ int FSattrib (FSFILE * file, unsigned char attributes)
1387+ Summary:
1388+ Change the attributes of a file
1389+ Conditions:
1390+ File opened
1391+ Input:
1392+ file - Pointer to file structure
1393+ attributes - The attributes to set for the file
1394+ - Attribute - Value - Indications
1395+ - ATTR_READ_ONLY - 0x01 - The read-only attribute
1396+ - ATTR_HIDDEN - 0x02 - The hidden attribute
1397+ - ATTR_SYSTEM - 0x04 - The system attribute
1398+ - ATTR_ARCHIVE - 0x20 - The archive attribute
1399+ Return Values:
1400+ 0 - Attribute change was successful
1401+ -1 - Attribute change was unsuccessful
1402+ Side Effects:
1403+ The FSerrno variable will be changed.
1404+ Description:
1405+ The FSattrib funciton will set the attributes of the specified file
1406+ to the attributes passed in by the user. This function will load the
1407+ file entry, replace the attributes with the ones specified, and write
1408+ the attributes back. If the specified file is a directory, the
1409+ directory attribute will be preserved.
1410+ Remarks:
1411+ None
1412+ ***************************************************************************/
1413+
1414+int FSattrib (FSFILE * file, unsigned char attributes);
1415+
1416+
1417+/***************************************************************
1418+ Function:
1419+ int FSrename (const rom char * fileName, FSFILE * fo)
1420+ Summary:
1421+ Change the Ascii name of a file or directory
1422+ Conditions:
1423+ File opened.
1424+ Input:
1425+ fileName - The new name of the file
1426+ fo - The file to rename
1427+ Return Values:
1428+ 0 - File was renamed successfully
1429+ EOF - File was not renamed
1430+ Side Effects:
1431+ The FSerrno variable will be changed.
1432+ Description:
1433+ The FSrename function will rename a file. First, it will
1434+ search through the current working directory to ensure the
1435+ specified new filename is not already in use. If it isn't,
1436+ the new filename will be written to the file entry of the
1437+ file pointed to by 'fo.'
1438+ Remarks:
1439+ None
1440+ ***************************************************************/
1441+
1442+int FSrename (const char * fileName, FSFILE * fo);
1443+
1444+#ifdef SUPPORT_LFN
1445+/***************************************************************
1446+ Function:
1447+ int wFSrename (const rom unsigned short int * fileName, FSFILE * fo)
1448+ Summary:
1449+ Change the name of a file or directory to the UTF16 input fileName
1450+ Conditions:
1451+ File opened.
1452+ Input:
1453+ fileName - The new name of the file
1454+ fo - The file to rename
1455+ Return Values:
1456+ 0 - File was renamed successfully
1457+ EOF - File was not renamed
1458+ Side Effects:
1459+ The FSerrno variable will be changed.
1460+ Description:
1461+ The wFSrename function will rename a file. First, it will
1462+ search through the current working directory to ensure the
1463+ specified new UTF16 filename is not already in use. If it isn't,
1464+ the new filename will be written to the file entry of the
1465+ file pointed to by 'fo.'
1466+ Remarks:
1467+ None
1468+ ***************************************************************/
1469+
1470+int wFSrename (const unsigned short int * fileName, FSFILE * fo);
1471+#endif
1472+
1473+/*********************************************************************
1474+ Function:
1475+ int FSremove (const char * fileName)
1476+ Summary:
1477+ Delete a Ascii file
1478+ Conditions:
1479+ File not opened, file exists
1480+ Input:
1481+ fileName - Name of the file to erase
1482+ Return Values:
1483+ 0 - File removed
1484+ EOF - File was not removed
1485+ Side Effects:
1486+ The FSerrno variable will be changed.
1487+ Description:
1488+ The FSremove function will attempt to find the specified file with
1489+ the FILEfind function. If the file is found, it will be erased
1490+ using the FILEerase function.The user can also provide ascii alias name
1491+ of the ascii long file name as the input to this function to get it erased
1492+ from the memory.
1493+ Remarks:
1494+ None
1495+ **********************************************************************/
1496+
1497+int FSremove (const char * fileName);
1498+
1499+#ifdef SUPPORT_LFN
1500+/*********************************************************************
1501+ Function:
1502+ int wFSremove (const unsigned short int * fileName)
1503+ Summary:
1504+ Delete a UTF16 file
1505+ Conditions:
1506+ File not opened, file exists
1507+ Input:
1508+ fileName - Name of the file to erase
1509+ Return Values:
1510+ 0 - File removed
1511+ EOF - File was not removed
1512+ Side Effects:
1513+ The FSerrno variable will be changed.
1514+ Description:
1515+ The wFSremove function will attempt to find the specified UTF16 file
1516+ name with the FILEfind function. If the file is found, it will be erased
1517+ using the FILEerase function.
1518+ Remarks:
1519+ None
1520+ **********************************************************************/
1521+
1522+int wFSremove (const unsigned short int * fileName);
1523+#endif
1524+
1525+/*********************************************************************************
1526+ Function:
1527+ size_t FSfwrite(const void *ptr, size_t size, size_t n, FSFILE *stream)
1528+ Summary:
1529+ Write data to a file
1530+ Conditions:
1531+ File opened in WRITE, APPEND, WRITE+, APPEND+, READ+ mode
1532+ Input:
1533+ ptr - Pointer to source buffer
1534+ size - Size of units in bytes
1535+ n - Number of units to transfer
1536+ stream - Pointer to file structure
1537+ Return:
1538+ size_t - number of units written
1539+ Side Effects:
1540+ The FSerrno variable will be changed.
1541+ Description:
1542+ The FSfwrite function will write data to a file. First, the sector that
1543+ corresponds to the current position in the file will be loaded (if it hasn't
1544+ already been cached in the global data buffer). Data will then be written to
1545+ the device from the specified buffer until the specified amount has been written.
1546+ If the end of a cluster is reached, the next cluster will be loaded, unless
1547+ the end-of-file flag for the specified file has been set. If it has, a new
1548+ cluster will be allocated to the file. Finally, the new position and filesize
1549+ will be stored in the FSFILE object. The parameters 'size' and 'n' indicate how
1550+ much data to write. 'Size' refers to the size of one object to write (in bytes),
1551+ and 'n' will refer to the number of these objects to write. The value returned
1552+ will be equal to 'n' unless an error occured.
1553+ Remarks:
1554+ None.
1555+ *********************************************************************************/
1556+
1557+size_t FSfwrite(const void *ptr, size_t size, size_t n, FSFILE *stream);
1558+
1559+#endif
1560+
1561+#ifdef ALLOW_DIRS
1562+
1563+
1564+/**************************************************************************
1565+ Function:
1566+ int FSchdir (char * path)
1567+ Summary:
1568+ Change the current working directory as per the path specified in Ascii format
1569+ Conditions:
1570+ None
1571+ Input:
1572+ path - The path of the directory to change to.
1573+ Return Values:
1574+ 0 - The current working directory was changed successfully
1575+ EOF - The current working directory could not be changed
1576+ Side Effects:
1577+ The current working directory may be changed. The FSerrno variable will
1578+ be changed.
1579+ Description:
1580+ The FSchdir function passes a RAM pointer to the path to the
1581+ chdirhelper function.
1582+ Remarks:
1583+ None
1584+ **************************************************************************/
1585+
1586+int FSchdir (char * path);
1587+
1588+#ifdef SUPPORT_LFN
1589+/**************************************************************************
1590+ Function:
1591+ int wFSchdir (unsigned short int * path)
1592+ Summary:
1593+ Change the current working directory as per the path specified in UTF16 format
1594+ Conditions:
1595+ None
1596+ Input:
1597+ path - The path of the directory to change to.
1598+ Return Values:
1599+ 0 - The current working directory was changed successfully
1600+ EOF - The current working directory could not be changed
1601+ Side Effects:
1602+ The current working directory may be changed. The FSerrno variable will
1603+ be changed.
1604+ Description:
1605+ The FSchdir function passes a RAM pointer to the path to the
1606+ chdirhelper function.
1607+ Remarks:
1608+ None
1609+ **************************************************************************/
1610+
1611+int wFSchdir (unsigned short int * path);
1612+#endif
1613+
1614+/**************************************************************
1615+ Function:
1616+ char * FSgetcwd (char * path, int numchars)
1617+ Summary:
1618+ Get the current working directory path in Ascii format
1619+ Conditions:
1620+ None
1621+ Input:
1622+ path - Pointer to the array to return the cwd name in
1623+ numchars - Number of chars in the path
1624+ Return Values:
1625+ char * - The cwd name string pointer (path or defaultArray)
1626+ NULL - The current working directory name could not be loaded.
1627+ Side Effects:
1628+ The FSerrno variable will be changed
1629+ Description:
1630+ The FSgetcwd function will get the name of the current
1631+ working directory and return it to the user. The name
1632+ will be copied into the buffer pointed to by 'path,'
1633+ starting at the root directory and copying as many chars
1634+ as possible before the end of the buffer. The buffer
1635+ size is indicated by the 'numchars' argument. The first
1636+ thing this function will do is load the name of the current
1637+ working directory, if it isn't already present. This could
1638+ occur if the user switched to the dotdot entry of a
1639+ subdirectory immediately before calling this function. The
1640+ function will then copy the current working directory name
1641+ into the buffer backwards, and insert a backslash character.
1642+ Next, the function will continuously switch to the previous
1643+ directories and copy their names backwards into the buffer
1644+ until it reaches the root. If the buffer overflows, it
1645+ will be treated as a circular buffer, and data will be
1646+ copied over existing characters, starting at the beginning.
1647+ Once the root directory is reached, the text in the buffer
1648+ will be swapped, so that the buffer contains as much of the
1649+ current working directory name as possible, starting at the
1650+ root.
1651+ Remarks:
1652+ None
1653+ **************************************************************/
1654+
1655+char * FSgetcwd (char * path, int numbchars);
1656+
1657+#ifdef SUPPORT_LFN
1658+/**************************************************************
1659+ Function:
1660+ char * wFSgetcwd (unsigned short int * path, int numchars)
1661+ Summary:
1662+ Get the current working directory path in UTF16 format
1663+ Conditions:
1664+ None
1665+ Input:
1666+ path - Pointer to the array to return the cwd name in
1667+ numchars - Number of chars in the path
1668+ Return Values:
1669+ char * - The cwd name string pointer (path or defaultArray)
1670+ NULL - The current working directory name could not be loaded.
1671+ Side Effects:
1672+ The FSerrno variable will be changed
1673+ Description:
1674+ The FSgetcwd function will get the name of the current
1675+ working directory and return it to the user. The name
1676+ will be copied into the buffer pointed to by 'path,'
1677+ starting at the root directory and copying as many chars
1678+ as possible before the end of the buffer. The buffer
1679+ size is indicated by the 'numchars' argument. The first
1680+ thing this function will do is load the name of the current
1681+ working directory, if it isn't already present. This could
1682+ occur if the user switched to the dotdot entry of a
1683+ subdirectory immediately before calling this function. The
1684+ function will then copy the current working directory name
1685+ into the buffer backwards, and insert a backslash character.
1686+ Next, the function will continuously switch to the previous
1687+ directories and copy their names backwards into the buffer
1688+ until it reaches the root. If the buffer overflows, it
1689+ will be treated as a circular buffer, and data will be
1690+ copied over existing characters, starting at the beginning.
1691+ Once the root directory is reached, the text in the buffer
1692+ will be swapped, so that the buffer contains as much of the
1693+ current working directory name as possible, starting at the
1694+ root.
1695+ Remarks:
1696+ None
1697+ **************************************************************/
1698+
1699+char * wFSgetcwd (unsigned short int * path, int numbchars);
1700+#endif
1701+
1702+#ifdef ALLOW_WRITES
1703+
1704+/**************************************************************************
1705+ Function:
1706+ int FSmkdir (char * path)
1707+ Summary:
1708+ Create a directory as per the Ascii input path
1709+ Conditions:
1710+ None
1711+ Input:
1712+ path - The path of directories to create.
1713+ Return Values:
1714+ 0 - The specified directory was created successfully
1715+ EOF - The specified directory could not be created
1716+ Side Effects:
1717+ Will create all non-existent directories in the path. The FSerrno
1718+ variable will be changed.
1719+ Description:
1720+ The FSmkdir function passes a RAM pointer to the path to the
1721+ mkdirhelper function.
1722+ Remarks:
1723+ None
1724+ **************************************************************************/
1725+
1726+int FSmkdir (char * path);
1727+
1728+#ifdef SUPPORT_LFN
1729+/**************************************************************************
1730+ Function:
1731+ int wFSmkdir (unsigned short int * path)
1732+ Summary:
1733+ Create a directory as per the UTF16 input path
1734+ Conditions:
1735+ None
1736+ Input:
1737+ path - The path of directories to create.
1738+ Return Values:
1739+ 0 - The specified directory was created successfully
1740+ EOF - The specified directory could not be created
1741+ Side Effects:
1742+ Will create all non-existent directories in the path. The FSerrno
1743+ variable will be changed.
1744+ Description:
1745+ The wFSmkdir function passes a RAM pointer to the path to the
1746+ mkdirhelper function.
1747+ Remarks:
1748+ None
1749+ **************************************************************************/
1750+
1751+int wFSmkdir (unsigned short int * path);
1752+#endif
1753+
1754+/**************************************************************************
1755+ Function:
1756+ int FSrmdir (char * path)
1757+ Summary:
1758+ Delete a directory as per the Ascii input path
1759+ Conditions:
1760+ None
1761+ Input:
1762+ path - The path of the directory to remove
1763+ rmsubdirs -
1764+ - TRUE - All sub-dirs and files in the target dir will be removed
1765+ - FALSE - FSrmdir will not remove non-empty directories
1766+ Return Values:
1767+ 0 - The specified directory was deleted successfully
1768+ EOF - The specified directory could not be deleted
1769+ Side Effects:
1770+ The FSerrno variable will be changed.
1771+ Description:
1772+ The FSrmdir function passes a RAM pointer to the path to the
1773+ rmdirhelper function.
1774+ Remarks:
1775+ None.
1776+ **************************************************************************/
1777+
1778+int FSrmdir (char * path, unsigned char rmsubdirs);
1779+
1780+#ifdef SUPPORT_LFN
1781+/**************************************************************************
1782+ Function:
1783+ int wFSrmdir (unsigned short int * path, unsigned char rmsubdirs)
1784+ Summary:
1785+ Delete a directory as per the UTF16 input path
1786+ Conditions:
1787+ None
1788+ Input:
1789+ path - The path of the directory to remove
1790+ rmsubdirs -
1791+ - TRUE - All sub-dirs and files in the target dir will be removed
1792+ - FALSE - FSrmdir will not remove non-empty directories
1793+ Return Values:
1794+ 0 - The specified directory was deleted successfully
1795+ EOF - The specified directory could not be deleted
1796+ Side Effects:
1797+ The FSerrno variable will be changed.
1798+ Description:
1799+ The wFSrmdir function passes a RAM pointer to the path to the
1800+ rmdirhelper function.
1801+ Remarks:
1802+ None.
1803+ **************************************************************************/
1804+
1805+int wFSrmdir (unsigned short int * path, unsigned char rmsubdirs);
1806+#endif
1807+
1808+#endif
1809+
1810+#endif
1811+
1812+#ifdef USERDEFINEDCLOCK
1813+
1814+
1815+/***********************************************************************************************************
1816+ Function:
1817+ int SetClockVars (unsigned int year, unsigned char month, unsigned char day, unsigned char hour, unsigned char minute, unsigned char second)
1818+ Summary:
1819+ Manually set timestamp variables
1820+ Conditions:
1821+ USERDEFINEDCLOCK macro defined in FSconfig.h.
1822+ Input:
1823+ year - The year (1980\-2107)
1824+ month - The month (1\-12)
1825+ day - The day of the month (1\-31)
1826+ hour - The hour (0\-23)
1827+ minute - The minute (0\-59)
1828+ second - The second (0\-59)
1829+ Return Values:
1830+ None
1831+ Side Effects:
1832+ Modifies global timing variables
1833+ Description:
1834+ Lets the user manually set the timing variables. The values passed in will be converted to the format
1835+ used by the FAT timestamps.
1836+ Remarks:
1837+ Call this before creating a file or directory (set create time) and
1838+ before closing a file (set last access time, last modified time)
1839+ ***********************************************************************************************************/
1840+
1841+int SetClockVars (unsigned int year, unsigned char month, unsigned char day, unsigned char hour, unsigned char minute, unsigned char second);
1842+#endif
1843+
1844+
1845+#ifdef ALLOW_FILESEARCH
1846+
1847+/***********************************************************************************
1848+ Function:
1849+ int FindFirst (const char * fileName, unsigned int attr, SearchRec * rec)
1850+ Summary:
1851+ Initial search function for the input Ascii fileName
1852+ Conditions:
1853+ None
1854+ Input:
1855+ fileName - The name to search for
1856+ - Parital string search characters
1857+ - * - Indicates the rest of the filename or extension can vary (e.g. FILE.*)
1858+ - ? - Indicates that one character in a filename can vary (e.g. F?LE.T?T)
1859+ attr - The attributes that a found file may have
1860+ - ATTR_READ_ONLY - File may be read only
1861+ - ATTR_HIDDEN - File may be a hidden file
1862+ - ATTR_SYSTEM - File may be a system file
1863+ - ATTR_VOLUME - Entry may be a volume label
1864+ - ATTR_DIRECTORY - File may be a directory
1865+ - ATTR_ARCHIVE - File may have archive attribute
1866+ - ATTR_MASK - All attributes
1867+ rec - pointer to a structure to put the file information in
1868+ Return Values:
1869+ 0 - File was found
1870+ -1 - No file matching the specified criteria was found
1871+ Side Effects:
1872+ Search criteria from previous FindFirst call on passed SearchRec object
1873+ will be lost. "utf16LFNfound" is overwritten after subsequent FindFirst/FindNext
1874+ operations.It is the responsibility of the application to read the "utf16LFNfound"
1875+ before it is lost.The FSerrno variable will be changed.
1876+ Description:
1877+ The FindFirst function will search for a file based on parameters passed in
1878+ by the user. This function will use the FILEfind function to parse through
1879+ the current working directory searching for entries that match the specified
1880+ parameters. If a file is found, its parameters are copied into the SearchRec
1881+ structure, as are the initial parameters passed in by the user and the position
1882+ of the file entry in the current working directory.If the return value of the
1883+ function is 0 then "utf16LFNfoundLength" indicates whether the file found was
1884+ long file name or short file name(8P3 format). The "utf16LFNfoundLength" is non-zero
1885+ for long file name and is zero for 8P3 format."utf16LFNfound" points to the
1886+ address of long file name if found during the operation.
1887+ Remarks:
1888+ Call FindFirst or FindFirstpgm before calling FindNext
1889+ ***********************************************************************************/
1890+
1891+int FindFirst (const char * fileName, unsigned int attr, SearchRec * rec);
1892+
1893+#ifdef SUPPORT_LFN
1894+/***********************************************************************************
1895+ Function:
1896+ int wFindFirst (const unsigned short int * fileName, unsigned int attr, SearchRec * rec)
1897+ Summary:
1898+ Initial search function for the input UTF16 fileName
1899+ Conditions:
1900+ None
1901+ Input:
1902+ fileName - The name to search for
1903+ - Parital string search characters
1904+ - * - Indicates the rest of the filename or extension can vary (e.g. FILE.*)
1905+ - ? - Indicates that one character in a filename can vary (e.g. F?LE.T?T)
1906+ attr - The attributes that a found file may have
1907+ - ATTR_READ_ONLY - File may be read only
1908+ - ATTR_HIDDEN - File may be a hidden file
1909+ - ATTR_SYSTEM - File may be a system file
1910+ - ATTR_VOLUME - Entry may be a volume label
1911+ - ATTR_DIRECTORY - File may be a directory
1912+ - ATTR_ARCHIVE - File may have archive attribute
1913+ - ATTR_MASK - All attributes
1914+ rec - pointer to a structure to put the file information in
1915+ Return Values:
1916+ 0 - File was found
1917+ -1 - No file matching the specified criteria was found
1918+ Side Effects:
1919+ Search criteria from previous wFindFirst call on passed SearchRec object
1920+ will be lost. "utf16LFNfound" is overwritten after subsequent wFindFirst/FindNext
1921+ operations.It is the responsibility of the application to read the "utf16LFNfound"
1922+ before it is lost.The FSerrno variable will be changed.
1923+ Description:
1924+ The wFindFirst function will search for a file based on parameters passed in
1925+ by the user. This function will use the FILEfind function to parse through
1926+ the current working directory searching for entries that match the specified
1927+ parameters. If a file is found, its parameters are copied into the SearchRec
1928+ structure, as are the initial parameters passed in by the user and the position
1929+ of the file entry in the current working directory.If the return value of the
1930+ function is 0 then "utf16LFNfoundLength" indicates whether the file found was
1931+ long file name or short file name(8P3 format). The "utf16LFNfoundLength" is non-zero
1932+ for long file name and is zero for 8P3 format."utf16LFNfound" points to the
1933+ address of long file name if found during the operation.
1934+ Remarks:
1935+ Call FindFirst or FindFirstpgm before calling FindNext
1936+ ***********************************************************************************/
1937+
1938+int wFindFirst (const unsigned short int * fileName, unsigned int attr, SearchRec * rec);
1939+#endif
1940+
1941+/**********************************************************************
1942+ Function:
1943+ int FindNext (SearchRec * rec)
1944+ Summary:
1945+ Sequential search function
1946+ Conditions:
1947+ None
1948+ Input:
1949+ rec - The structure to store the file information in
1950+ Return Values:
1951+ 0 - File was found
1952+ -1 - No additional files matching the specified criteria were found
1953+ Side Effects:
1954+ Search criteria from previous FindNext call on passed SearchRec object
1955+ will be lost. "utf16LFNfound" is overwritten after subsequent FindFirst/FindNext
1956+ operations.It is the responsibility of the application to read the "utf16LFNfound"
1957+ before it is lost.The FSerrno variable will be changed.
1958+ Description:
1959+ The FindNext function performs the same function as the FindFirst
1960+ funciton, except it does not copy any search parameters into the
1961+ SearchRec structure (only info about found files) and it begins
1962+ searching at the last directory entry offset at which a file was
1963+ found, rather than at the beginning of the current working
1964+ directory.If the return value of the function is 0 then "utf16LFNfoundLength"
1965+ indicates whether the file found was long file name or short file
1966+ name(8P3 format). The "utf16LFNfoundLength" is non-zero for long file name
1967+ and is zero for 8P3 format."utf16LFNfound" points to the address of long
1968+ file name if found during the operation.
1969+ Remarks:
1970+ Call FindFirst or FindFirstpgm before calling this function
1971+ **********************************************************************/
1972+
1973+int FindNext (SearchRec * rec);
1974+#endif
1975+
1976+
1977+/**********************************************************************
1978+ Function:
1979+ // PIC24/30/33/32
1980+ int FSfprintf (FSFILE * fptr, const char * fmt, ...)
1981+ // PIC18
1982+ int FSfpritnf (FSFILE * fptr, const rom char * fmt, ...)
1983+ Summary:
1984+ Function to write formatted strings to a file
1985+ Conditions:
1986+ For PIC18, integer promotion must be enabled in the project build
1987+ options menu. File opened in a write mode.
1988+ Input:
1989+ fptr - A pointer to the file to write to.
1990+ fmt - A string of characters and format specifiers to write to
1991+ the file
1992+ ... - Additional arguments inserted in the string by format
1993+ specifiers
1994+ Returns:
1995+ The number of characters written to the file
1996+ Side Effects:
1997+ The FSerrno variable will be changed.
1998+ Description:
1999+ Writes a specially formatted string to a file.
2000+ Remarks:
2001+ Consult AN1045 for a full description of how to use format
2002+ specifiers.
2003+ **********************************************************************/
2004+
2005+#ifdef ALLOW_FSFPRINTF
2006+ #ifdef __18CXX
2007+ int FSfprintf (FSFILE *fptr, const rom char *fmt, ...);
2008+ #else
2009+ int FSfprintf (FSFILE *fptr, const char * fmt, ...);
2010+ #endif
2011+#endif
2012+
2013+
2014+/**************************************************************************
2015+ Function:
2016+ int FSerror (void)
2017+ Summary:
2018+ Return an error code for the last function call
2019+ Conditions:
2020+ The return value depends on the last function called.
2021+ Input:
2022+ None
2023+ Side Effects:
2024+ None.
2025+ Return Values:
2026+ FSInit -
2027+ - CE_GOOD ・ No Error
2028+ - CE_INIT_ERROR ・ The physical media could not be initialized
2029+ - CE_BAD_SECTOR_READ ・ The MBR or the boot sector could not be
2030+ read correctly
2031+ - CE_BAD_PARITION ・ The MBR signature code was incorrect.
2032+ - CE_NOT_FORMATTED ・ The boot sector signature code was incorrect or
2033+ indicates an invalid number of bytes per sector.
2034+ - CE_CARDFAT32 ・ The physical media is FAT32 type (only an error
2035+ when FAT32 support is disabled).
2036+ - CE_UNSUPPORTED_FS ・ The device is formatted with an unsupported file
2037+ system (not FAT12 or 16).
2038+ FSfopen -
2039+ - CE_GOOD ・ No Error
2040+ - CE_NOT_INIT ・ The device has not been initialized.
2041+ - CE_TOO_MANY_FILES_OPEN ・ The function could not allocate any
2042+ additional file information to the array
2043+ of FSFILE structures or the heap.
2044+ - CE_INVALID_FILENAME ・ The file name argument was invalid.
2045+ - CE_INVALID_ARGUMENT ・ The user attempted to open a directory in a
2046+ write mode or specified an invalid mode argument.
2047+ - CE_FILE_NOT_FOUND ・ The specified file (which was to be opened in read
2048+ mode) does not exist on the device.
2049+ - CE_BADCACHEREAD ・ A read from the device failed.
2050+ - CE_ERASE_FAIL ・ The existing file could not be erased (when opening
2051+ a file in WRITE mode).
2052+ - CE_DIR_FULL ・ The directory is full.
2053+ - CE_DISK_FULL・ The data memory section is full.
2054+ - CE_WRITE_ERROR ・ A write to the device failed.
2055+ - CE_SEEK_ERROR ・ The current position in the file could not be set to
2056+ the end (when the file was opened in APPEND mode).
2057+ FSfclose -
2058+ - CE_GOOD ・ No Error
2059+ - CE_WRITE_ERROR ・ The existing data in the data buffer or the new file
2060+ entry information could not be written to the device.
2061+ - CE_BADCACHEREAD ・ The file entry information could not be cached
2062+ FSfread -
2063+ - CE_GOOD ・ No Error
2064+ - CE_WRITEONLY ・ The file was opened in a write-only mode.
2065+ - CE_WRITE_ERROR ・ The existing data in the data buffer could not be
2066+ written to the device.
2067+ - CE_BAD_SECTOR_READ ・ The data sector could not be read.
2068+ - CE_EOF ・ The end of the file was reached.
2069+ - CE_COULD_NOT_GET_CLUSTER ・Additional clusters in the file could not be loaded.
2070+ FSfwrite -
2071+ - CE_GOOD ・ No Error
2072+ - CE_READONLY ・ The file was opened in a read-only mode.
2073+ - CE_WRITE_PROTECTED ・ The device write-protect check function indicated
2074+ that the device has been write-protected.
2075+ - CE_WRITE_ERROR ・ There was an error writing data to the device.
2076+ - CE_BADCACHEREAD ・ The data sector to be modified could not be read from
2077+ the device.
2078+ - CE_DISK_FULL ・ All data clusters on the device are in use.
2079+ FSfseek -
2080+ - CE_GOOD ・ No Error
2081+ - CE_WRITE_ERROR ・ The existing data in the data buffer could not be
2082+ written to the device.
2083+ - CE_INVALID_ARGUMENT ・ The specified offset exceeds the size of the file.
2084+ - CE_BADCACHEREAD ・ The sector that contains the new current position
2085+ could not be loaded.
2086+ - CE_COULD_NOT_GET_CLUSTER ・Additional clusters in the file could not be
2087+ loaded/allocated.
2088+ FSftell -
2089+ - CE_GOOD ・ No Error
2090+ FSattrib -
2091+ - CE_GOOD ・ No Error
2092+ - CE_INVALID_ARGUMENT ・ The attribute argument was invalid.
2093+ - CE_BADCACHEREAD ・ The existing file entry information could not be
2094+ loaded.
2095+ - CE_WRITE_ERROR ・ The file entry information could not be written to
2096+ the device.
2097+ FSrename -
2098+ - CE_GOOD ・ No Error
2099+ - CE_FILENOTOPENED ・ A null file pointer was passed into the function.
2100+ - CE_INVALID_FILENAME ・ The file name passed into the function was invalid.
2101+ - CE_BADCACHEREAD ・ A read from the device failed.
2102+ - CE_FILENAME_EXISTS ・ A file with the specified name already exists.
2103+ - CE_WRITE_ERROR ・ The new file entry data could not be written to the
2104+ device.
2105+ FSfeof -
2106+ - CE_GOOD ・ No Error
2107+ FSformat -
2108+ - CE_GOOD ・ No Error
2109+ - CE_INIT_ERROR ・ The device could not be initialized.
2110+ - CE_BADCACHEREAD ・ The master boot record or boot sector could not be
2111+ loaded successfully.
2112+ - CE_INVALID_ARGUMENT ・ The user selected to create their own boot sector on
2113+ a device that has no master boot record, or the mode
2114+ argument was invalid.
2115+ - CE_WRITE_ERROR ・ The updated MBR/Boot sector could not be written to
2116+ the device.
2117+ - CE_BAD_PARTITION ・ The calculated number of sectors per clusters was
2118+ invalid.
2119+ - CE_NONSUPPORTED_SIZE ・ The card has too many sectors to be formatted as
2120+ FAT12 or FAT16.
2121+ FSremove -
2122+ - CE_GOOD ・ No Error
2123+ - CE_WRITE_PROTECTED ・ The device write-protect check function indicated
2124+ that the device has been write-protected.
2125+ - CE_INVALID_FILENAME ・ The specified filename was invalid.
2126+ - CE_FILE_NOT_FOUND ・ The specified file could not be found.
2127+ - CE_ERASE_FAIL ・ The file could not be erased.
2128+ FSchdir -
2129+ - CE_GOOD ・ No Error
2130+ - CE_INVALID_ARGUMENT ・ The path string was mis-formed or the user tried to
2131+ change to a non-directory file.
2132+ - CE_BADCACHEREAD ・ A directory entry could not be cached.
2133+ - CE_DIR_NOT_FOUND ・ Could not find a directory in the path.
2134+ FSgetcwd -
2135+ - CE_GOOD ・ No Error
2136+ - CE_INVALID_ARGUMENT ・ The user passed a 0-length buffer into the function.
2137+ - CE_BADCACHEREAD ・ A directory entry could not be cached.
2138+ - CE_BAD_SECTOR_READ ・ The function could not determine a previous directory
2139+ of the current working directory.
2140+ FSmkdir -
2141+ - CE_GOOD ・ No Error
2142+ - CE_WRITE_PROTECTED ・ The device write-protect check function indicated
2143+ that the device has been write-protected.
2144+ - CE_INVALID_ARGUMENT ・ The path string was mis-formed.
2145+ - CE_BADCACHEREAD ・ Could not successfully change to a recently created
2146+ directory to store its dir entry information, or
2147+ could not cache directory entry information.
2148+ - CE_INVALID_FILENAME ・ One or more of the directory names has an invalid
2149+ format.
2150+ - CE_WRITE_ERROR ・ The existing data in the data buffer could not be
2151+ written to the device or the dot/dotdot entries could
2152+ not be written to a newly created directory.
2153+ - CE_DIR_FULL ・ There are no available dir entries in the CWD.
2154+ - CE_DISK_FULL ・ There are no available clusters in the data region of
2155+ the device.
2156+ FSrmdir -
2157+ - CE_GOOD ・ No Error
2158+ - CE_DIR_NOT_FOUND ・ The directory specified could not be found or the
2159+ function could not change to a subdirectory within
2160+ the directory to be deleted (when recursive delete is
2161+ enabled).
2162+ - CE_INVALID_ARGUMENT ・ The user tried to remove the CWD or root directory.
2163+ - CE_BADCACHEREAD ・ A directory entry could not be cached.
2164+ - CE_DIR_NOT_EMPTY ・ The directory to be deleted was not empty and
2165+ recursive subdirectory removal was disabled.
2166+ - CE_ERASE_FAIL ・ The directory or one of the directories or files
2167+ within it could not be deleted.
2168+ - CE_BAD_SECTOR_READ ・ The function could not determine a previous directory
2169+ of the CWD.
2170+ SetClockVars -
2171+ - CE_GOOD ・ No Error
2172+ - CE_INVALID_ARGUMENT ・ The time values passed into the function were
2173+ invalid.
2174+ FindFirst -
2175+ - CE_GOOD ・ No Error
2176+ - CE_INVALID_FILENAME ・ The specified filename was invalid.
2177+ - CE_FILE_NOT_FOUND ・ No file matching the specified criteria was found.
2178+ - CE_BADCACHEREAD ・ The file information for the file that was found
2179+ could not be cached.
2180+ FindNext -
2181+ - CE_GOOD ・ No Error
2182+ - CE_NOT_INIT ・ The SearchRec object was not initialized by a call to
2183+ FindFirst.
2184+ - CE_INVALID_ARGUMENT ・ The SearchRec object was initialized in a different
2185+ directory from the CWD.
2186+ - CE_INVALID_FILENAME ・ The filename is invalid.
2187+ - CE_FILE_NOT_FOUND ・ No file matching the specified criteria was found.
2188+ FSfprintf -
2189+ - CE_GOOD ・ No Error
2190+ - CE_WRITE_ERROR ・ Characters could not be written to the file.
2191+ Description:
2192+ The FSerror function will return the FSerrno variable. This global
2193+ variable will have been set to an error value during the last call of a
2194+ library function.
2195+ Remarks:
2196+ None
2197+ **************************************************************************/
2198+
2199+int FSerror (void);
2200+
2201+
2202+/*********************************************************************************
2203+ Function:
2204+ int FSCreateMBR (unsigned long firstSector, unsigned long numSectors)
2205+ Summary:
2206+ Creates a master boot record
2207+ Conditions:
2208+ The I/O pins for the device have been initialized by the InitIO function.
2209+ Input:
2210+ firstSector - The first sector of the partition on the device (cannot
2211+ be 0; that's the MBR)
2212+ numSectors - The number of sectors available in memory (including the
2213+ MBR)
2214+ Return Values:
2215+ 0 - MBR was created successfully
2216+ EOF - MBR could not be created
2217+ Side Effects:
2218+ None
2219+ Description:
2220+ This function can be used to create a master boot record for a device. Note
2221+ that this function should not be used on a device that is already formatted
2222+ with a master boot record (i.e. most SD cards, CF cards, USB keys). This
2223+ function will fill the global data buffer with appropriate partition information
2224+ for a FAT partition with a type determined by the number of sectors available
2225+ to the partition. It will then write the MBR information to the first sector
2226+ on the device. This function should be followed by a call to FSformat, which
2227+ will create a boot sector, root dir, and FAT appropriate the the information
2228+ contained in the new master boot record. Note that FSformat only supports
2229+ FAT12 and FAT16 formatting at this time, and so cannot be used to format a
2230+ device with more than 0x3FFD5F sectors.
2231+ Remarks:
2232+ This function can damage the device being used, and should not be called
2233+ unless the user is sure about the size of the device and the first sector value.
2234+ *********************************************************************************/
2235+
2236+int FSCreateMBR (unsigned long firstSector, unsigned long numSectors);
2237+
2238+
2239+#ifdef ALLOW_GET_DISK_PROPERTIES
2240+/*********************************************************************************
2241+ Function:
2242+ void FSGetDiskProperties(FS_DISK_PROPERTIES* properties)
2243+ Summary:
2244+ Allows user to get the disk properties (size of disk, free space, etc)
2245+ Conditions:
2246+ 1) ALLOW_GET_DISK_PROPERTIES must be defined in FSconfig.h
2247+ 2) a FS_DISK_PROPERTIES object must be created before the function is called
2248+ 3) the new_request member of the FS_DISK_PROPERTIES object must be set before
2249+ calling the function for the first time. This will start a new search.
2250+ 4) this function should not be called while there is a file open. Close all
2251+ files before calling this function.
2252+ Input:
2253+ properties - a pointer to a FS_DISK_PROPERTIES object where the results should
2254+ be stored.
2255+ Return Values:
2256+ This function returns void. The properties_status of the previous call of
2257+ this function is located in the properties.status field. This field has
2258+ the following possible values:
2259+
2260+ FS_GET_PROPERTIES_NO_ERRORS - operation completed without error. Results
2261+ are in the properties object passed into the function.
2262+ FS_GET_PROPERTIES_DISK_NOT_MOUNTED - there is no mounted disk. Results in
2263+ properties object is not valid
2264+ FS_GET_PROPERTIES_CLUSTER_FAILURE - there was a failure trying to read a
2265+ cluster from the drive. The results in the properties object is a partial
2266+ result up until the point of the failure.
2267+ FS_GET_PROPERTIES_STILL_WORKING - the search for free sectors is still in
2268+ process. Continue calling this function with the same properties pointer
2269+ until either the function completes or until the partial results meets the
2270+ application needs. The properties object contains the partial results of
2271+ the search and can be used by the application.
2272+ Side Effects:
2273+ Can cause errors if called when files are open. Close all files before
2274+ calling this function.
2275+
2276+ Calling this function without setting the new_request member on the first
2277+ call can result in undefined behavior and results.
2278+
2279+ Calling this function after a result is returned other than
2280+ FS_GET_PROPERTIES_STILL_WORKING can result in undefined behavior and results.
2281+ Description:
2282+ This function returns the information about the mounted drive. The results
2283+ member of the properties object passed into the function is populated with
2284+ the information about the drive.
2285+
2286+ Before starting a new request, the new_request member of the properties
2287+ input parameter should be set to TRUE. This will initiate a new search
2288+ request.
2289+
2290+ This function will return before the search is complete with partial results.
2291+ All of the results except the free_clusters will be correct after the first
2292+ call. The free_clusters will contain the number of free clusters found up
2293+ until that point, thus the free_clusters result will continue to grow until
2294+ the entire drive is searched. If an application only needs to know that a
2295+ certain number of bytes is available and doesn't need to know the total free
2296+ size, then this function can be called until the required free size is
2297+ verified. To continue a search, pass a pointer to the same FS_DISK_PROPERTIES
2298+ object that was passed in to create the search.
2299+
2300+ A new search request sould be made once this function has returned a value
2301+ other than FS_GET_PROPERTIES_STILL_WORKING. Continuing a completed search
2302+ can result in undefined behavior or results.
2303+
2304+ Typical Usage:
2305+ <code>
2306+ FS_DISK_PROPERTIES disk_properties;
2307+
2308+ disk_properties.new_request = TRUE;
2309+
2310+ do
2311+ {
2312+ FSGetDiskProperties(&disk_properties);
2313+ } while (disk_properties.properties_status == FS_GET_PROPERTIES_STILL_WORKING);
2314+ </code>
2315+
2316+ results.disk_format - contains the format of the drive. Valid results are
2317+ FAT12(1), FAT16(2), or FAT32(3).
2318+
2319+ results.sector_size - the sector size of the mounted drive. Valid values are
2320+ 512, 1024, 2048, and 4096.
2321+
2322+ results.sectors_per_cluster - the number sectors per cluster.
2323+
2324+ results.total_clusters - the number of total clusters on the drive. This
2325+ can be used to calculate the total disk size (total_clusters *
2326+ sectors_per_cluster * sector_size = total size of drive in bytes)
2327+
2328+ results.free_clusters - the number of free (unallocated) clusters on the drive.
2329+ This can be used to calculate the total free disk size (free_clusters *
2330+ sectors_per_cluster * sector_size = total size of drive in bytes)
2331+
2332+ Remarks:
2333+ PIC24F size estimates:
2334+ Flash - 400 bytes (-Os setting)
2335+
2336+ PIC24F speed estimates:
2337+ Search takes approximately 7 seconds per Gigabyte of drive space. Speed
2338+ will vary based on the number of sectors per cluster and the sector size.
2339+ *********************************************************************************/
2340+void FSGetDiskProperties(FS_DISK_PROPERTIES* properties);
2341+#endif
2342+
2343+
2344+#endif