• 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

Revisão268 (tree)
Hora2018-08-04 05:12:38
Autorkmorimatsu

Mensagem de Log

Megalopa trunk

Mudança Sumário

Diff

--- mips/trunk/megalopa/lib_video_megalopa.h (nonexistent)
+++ mips/trunk/megalopa/lib_video_megalopa.h (revision 268)
@@ -0,0 +1,140 @@
1+// lib_video_megalopa.h
2+// テキスト+グラフィックビデオ出力 PIC32MX370F512H用ヘッダーファイル by K.Tanaka
3+
4+#define X_RES 288 // Graphic横方向解像度
5+#define X_RESW 384 // Graphic横方向解像度(ワイド時)
6+#define X_RESZ 256 // Graphic横方向解像度(type Z互換時)
7+#define Y_RES 216 // Graphic縦方向解像度
8+#define Y_RESZ 224 // Graphic縦方向解像度(type Z互換時)
9+#define WIDTH_X 36 // 横方向文字数
10+#define WIDTH_Y 27 // 縦方向文字数
11+#define WIDTH_XW 48 // 横方向文字数(ワイド時)
12+#define WIDTH_XW2 64 // 横方向文字数(ワイド、6ドットフォント時)
13+#define WIDTH_XBW 80 // 横方向文字数(モノクロ時)
14+#define WIDTH_30 30 // 横方向文字数(互換モード8ドットフォント時)
15+#define WIDTH_40 40 // 横方向文字数(互換モード6ドットフォント時)
16+#define ATTROFFSET (WIDTH_X*WIDTH_Y) // TVRAM上のカラーパレット格納位置(標準時)
17+#define ATTROFFSETW (WIDTH_XW*WIDTH_Y) // TVRAM上のカラーパレット格納位置(ワイド時)
18+#define ATTROFFSETW2 (WIDTH_XW2*WIDTH_Y) // TVRAM上のカラーパレット格納位置(ワイド、6ドットフォント時)
19+#define ATTROFFSETBW (WIDTH_XBW*WIDTH_Y) // TVRAM上のカラーパレット格納位置(モノクロ時)
20+#define ATTROFFSET30 (WIDTH_30*WIDTH_Y) // TVRAM上のカラーパレット格納位置(互換モード8ドットフォント時)
21+#define ATTROFFSET40 (WIDTH_40*WIDTH_Y) // TVRAM上のカラーパレット格納位置(互換モード6ドットフォント時)
22+#define WIDTH_XMAX WIDTH_XBW // 横方向最大文字数
23+
24+// videomode値
25+#define VMODE_T30 0 // 標準テキスト30文字互換モード
26+#define VMODE_STDTEXT 1 // 標準テキスト36文字モード
27+#define VMODE_T40 2 // 標準テキスト40文字互換モード(6ドットフォント)
28+#define VMODE_WIDETEXT 3 // ワイドテキスト48文字モード
29+#define VMODE_WIDETEXT6dot 4 // ワイドテキスト64文字モード(6ドットフォント)
30+#define VMODE_MONOTEXT 5 // モノクロテキスト80文字モード
31+#define VMODE_ZOEAGRPH 16 // type Z互換グラフィックモード
32+#define VMODE_STDGRPH 17 // 標準グラフィック+テキスト36文字モード
33+#define VMODE_WIDEGRPH 18 // ワイドグラフィック+テキスト48文字モード
34+
35+// textomode値
36+#define TMODE_T30 0 // 標準テキスト30文字互換モード
37+#define TMODE_STDTEXT 1 // 標準テキスト36文字モード
38+#define TMODE_T40 2 // 標準テキスト40文字互換モード(6ドットフォント)
39+#define TMODE_WIDETEXT 3 // ワイドテキスト48文字モード
40+#define TMODE_WIDETEXT6dot 4 // ワイドテキスト64文字モード(6ドットフォント)
41+#define TMODE_MONOTEXT 5 // モノクロテキスト80文字モード
42+
43+// graphmode値
44+#define GMODE_NOGRPH 0 // グラフィック不使用
45+#define GMODE_ZOEAGRPH 1 // type Z互換グラフィックモード
46+#define GMODE_STDGRPH 2 // 標準グラフィック+テキスト36文字モード
47+#define GMODE_WIDEGRPH 3 // ワイドグラフィック+テキスト48文字モード
48+
49+#define KEYPORT PORTD
50+#define KEYUP 0x0004
51+#define KEYDOWN 0x0001
52+#define KEYLEFT 0x0002
53+#define KEYRIGHT 0x0008
54+#define KEYSTART 0x0010
55+#define KEYFIRE 0x0020
56+
57+extern volatile char drawing; // 表示期間中は-1
58+extern volatile unsigned short drawcount; // 1画面表示終了ごとに1足す。アプリ側で0にする。
59+ // 最低1回は画面表示したことのチェックと、アプリの処理が何画面期間必要かの確認に利用。
60+extern unsigned char *GVRAM; // Graphicビデオメモリ
61+extern unsigned char TVRAM[]; // Characterビデオメモリ
62+extern const unsigned char FontData[]; //フォントパターン(初期化時にここからfontdata[]にコピー)
63+extern const unsigned char FontData2[]; //フォントパターン6ドットフォント
64+extern unsigned char videomode,textmode,graphmode; //画面モード
65+extern int twidth,twidthy; //テキスト文字数(横)および(縦
66+extern int attroffset; // TVRAMのカラー情報エリア位置
67+extern int gwidth,gwidthy; // グラフィックX方向解像度
68+extern unsigned char fontdata[]; //固定フォント領域、初期化時にFontData[]からコピー
69+extern unsigned char *Fontp; //現在のフォントパターンの先頭アドレス
70+
71+void start_composite(void); //カラーコンポジット出力開始
72+void stop_composite(void); //カラーコンポジット出力停止
73+void init_composite(void); //カラーコンポジット出力初期化
74+void init_palette(void); //カラーパレット初期化
75+void g_clearscreen(void); //Graphic画面クリア
76+void clearscreen(void); //Character画面クリア
77+void set_palette(unsigned char n,unsigned char b,unsigned char r,unsigned char g); //カラーパレット設定
78+void set_bgcolor(unsigned char b,unsigned char r,unsigned char g); // バックグラウンドカラー設定
79+void set_videomode(unsigned char m, unsigned char *gvram); //ビデオモードの切り替え
80+
81+// 以下は text_graph_library.c ライブラリを使用するための宣言
82+
83+// グラフィック画面関連
84+void g_pset(int x,int y,unsigned int c);
85+ // (x,y)の位置にカラーcで点を描画
86+void g_putbmpmn(int x,int y,char m,char n,const unsigned char bmp[]);
87+ // 横m*縦nドットのキャラクターを座標x,yに表示
88+ // unsigned char bmp[m*n]配列に、単純にカラー番号を並べる
89+ // カラー番号が0の部分は透明色として扱う
90+void g_clrbmpmn(int x,int y,char m,char n);
91+ // 縦m*横nドットのキャラクター消去
92+ // カラー0で塗りつぶし
93+void g_gline(int x1,int y1,int x2,int y2,unsigned int c);
94+ // (x1,y1)-(x2,y2)にカラーcで線分を描画
95+void g_hline(int x1,int x2,int y,unsigned int c);
96+ // (x1,y)-(x2,y)の水平ラインをカラーcで高速描画
97+void g_boxfill(int x1,int y1,int x2,int y2,unsigned int c);
98+ //座標(x1,y1),(x2,y2)を対角線とするカラーcで塗られた長方形を描画
99+ // (x1,y1),(x2,y2)を対角線とするカラーcで塗られた長方形を描画
100+void g_circle(int x0,int y0,unsigned int r,unsigned int c);
101+ // (x0,y0)を中心に、半径r、カラーcの円を描画
102+void g_circlefill(int x0,int y0,unsigned int r,unsigned int c);
103+ // (x0,y0)を中心に、半径r、カラーcで塗られた円を描画
104+void g_putfont(int x,int y,unsigned int c,int bc,unsigned char n);
105+ //8*8ドットのアルファベットフォント表示
106+ //座標(x,y)、カラー番号c
107+ //bc:バックグランドカラー、負数の場合無視
108+ //n:文字番号
109+void g_printstr(int x,int y,unsigned int c,int bc,unsigned char *s);
110+ //座標(x,y)からカラー番号cで文字列sを表示、bc:バックグランドカラー
111+void g_printnum(int x,int y,unsigned char c,int bc,unsigned int n);
112+ //座標(x,y)にカラー番号cで数値nを表示、bc:バックグランドカラー
113+void g_printnum2(int x,int y,unsigned char c,int bc,unsigned int n,unsigned char e);
114+ //座標(x,y)にカラー番号cで数値nを表示、bc:バックグランドカラー、e桁で表示
115+unsigned int g_color(int x,int y);
116+//座標(x,y)のVRAM上の現在のパレット番号を返す、画面外は0を返す
117+
118+//テキスト画面関連
119+extern unsigned char *cursor;
120+extern unsigned char cursorcolor;
121+void vramscroll(void);
122+ //1行スクロール
123+void setcursor(unsigned char x,unsigned char y,unsigned char c);
124+ //カーソル位置とカラーを設定
125+void setcursorcolor(unsigned char c);
126+ //カーソル位置そのままでカラー番号をcに設定
127+void printchar(unsigned char n);
128+ //カーソル位置にテキストコードnを1文字表示し、カーソルを1文字進める
129+void printstr(unsigned char *s);
130+ //カーソル位置に文字列sを表示
131+void printnum(unsigned int n);
132+ //カーソル位置に符号なし整数nを10進数表示
133+void printnum2(unsigned int n,unsigned char e);
134+ //カーソル位置に符号なし整数nをe桁の10進数表示(前の空き桁部分はスペースで埋める)
135+void cls(void);
136+ //テキスト画面を0でクリアし、カーソルを画面先頭に移動
137+void startPCG(unsigned char *p,int a);
138+ // RAMフォント(PCG)の利用開始、pがフォント格納場所、aが0以外でシステムフォントをコピー
139+void stopPCG(void);
140+ // RAMフォント(PCG)の利用停止
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
--- mips/trunk/megalopa/help.txt (nonexistent)
+++ mips/trunk/megalopa/help.txt (revision 268)
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
--- mips/trunk/megalopa/main.c (nonexistent)
+++ mips/trunk/megalopa/main.c (revision 268)
@@ -0,0 +1,360 @@
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 Megalopa
10+// KM-BASIC 統合開発実行環境 for PIC32MX370F512H by K.Tanaka
11+
12+// 利用システム
13+// ps2keyboard370f.X.a : PS/2キーボード入力システムライブラリ
14+// lib_videoout_megalopa.X.a : カラービデオ信号出力システムライブラリ
15+// sdfsio370fLib.a : SDカードアクセス用ライブラリ
16+
17+
18+/*
19+ PIC32MX ペリフェラル使用状況
20+
21+ 割り込み
22+ NTSC, Timer2, vector 8, priority 5
23+ NTSC, OC5, vector 22, priority 5
24+ NTSC, OC2, vector 10, priority 5
25+ NTSC, OC1, vector 6, priority 5
26+ PS/2, CNF, vector 33, priority 6
27+ PS/2, Timer5, vector 20, priority 4
28+ MUSIC, CS0, vector 1, priority 2
29+ SERIAL, UART, vector 31, priority 3
30+
31+ タイマー
32+ Timer1 未使用
33+ Timer2 NTSC
34+ Timer3 MUSIC/PWM
35+ Timer4 MUSIC
36+ Timer5 PS/2
37+
38+ DMA
39+ DMA0 未使用
40+ DMA1 MUSIC
41+ DMA2 MUSIC
42+ DMA3 PS/2
43+
44+ Output compair
45+ OC1 NTSC
46+ OC2 NTSC
47+ OC3 MUSIC/PWM
48+ OC4 MUSIC/PWM
49+ OC5 NTSC
50+
51+ UART
52+ UART1 シリアル通信
53+ UART2 未使用
54+
55+ SPI
56+ SPI1 SPI通信(予定)
57+ SPI2 マルチメディアカード
58+
59+ I2C
60+ I2C1 I2C通信(予定)
61+ I2C2 未使用
62+
63+ ポート使用
64+ B0 I/O, AN0
65+ B1 I/O, AN1
66+ B2 I/O, AN2
67+ B3 I/O, AN3
68+ B4 I/O, AN4
69+ B5 I/O, AN5
70+ B6 I/O, AN6
71+ B7 I/O, AN7
72+ B8 I/O, AN8
73+ B9 I/O, AN9
74+ B10 I/O, AN10
75+ B11 I/O, AN11
76+ B12 I/O, AN12
77+ B13 I/O, AN13
78+ B14 I/O, AN14
79+ B15 I/O, AN15
80+ C12 OSC1 (Crystal)
81+ C13 U1TX (UART)
82+ C14 U1RX (UART)
83+ C15 OSC2 (Crystal)
84+ D0 SW_DOWN
85+ D1 SW_LEFT
86+ D2 SW_UP
87+ D3 SW_RIGHT
88+ D4 SW_START
89+ D5 SW_FIRE
90+ D6
91+ D7
92+ D8
93+ D9 SPI1_CS (SPI)
94+ D10 PWM1
95+ D11 PWM2
96+ E0 NTSC
97+ E1 NTSC
98+ E2 NTSC
99+ E3 NTSC
100+ E4 NTSC
101+ E5 I/O, AN22
102+ E6 I/O, AN23
103+ E7 I/O, AN27
104+ F0 PS/2 DAT
105+ F1 PS/2 CLK
106+ F2 SDI1 (SPI)
107+ F3 SPI2_CS (MMC)
108+ F4 AUDIO_R
109+ F5 AUDIO_L
110+ F6 SCK1 (SPI)
111+ G2 SCL1 (I2C)
112+ G3 SDA1 (I2C)
113+ G6 SCK2 (MMC)
114+ G7 SDI2 (MMC)
115+ G8 SDO2 (MMC)
116+ G9 SDO1 (SPI)
117+*/
118+
119+#include <xc.h>
120+#include "api.h"
121+#include "compiler.h"
122+#include "editor.h"
123+#include "keyinput.h"
124+#include "main.h"
125+
126+//外付けクリスタル with PLL (20/3倍)
127+//クリスタルは3.579545×4=14.31818MHz
128+#pragma config FSRSSEL = PRIORITY_7
129+#pragma config PMDL1WAY = OFF
130+#pragma config IOL1WAY = OFF
131+//#pragma config FUSBIDIO = OFF
132+//#pragma config FVBUSONIO = OFF
133+#pragma config FPLLIDIV = DIV_3
134+#pragma config FPLLMUL = MUL_20
135+//#pragma config UPLLIDIV = DIV_1
136+//#pragma config UPLLEN = OFF
137+#pragma config FPLLODIV = DIV_1
138+#pragma config FNOSC = PRIPLL
139+#pragma config FSOSCEN = OFF
140+#pragma config IESO = OFF
141+#pragma config POSCMOD = XT
142+#pragma config OSCIOFNC = OFF
143+#pragma config FPBDIV = DIV_1
144+#pragma config FCKSM = CSDCMD
145+#pragma config FWDTEN = OFF
146+#pragma config DEBUG = OFF
147+#pragma config PWP = OFF
148+#pragma config BWP = OFF
149+#pragma config CP = OFF
150+
151+#define mBMXSetRAMKernProgOffset(offset) (BMXDKPBA = (offset))
152+#define mBMXSetRAMUserDataOffset(offset) (BMXDUDBA = (offset))
153+#define mBMXSetRAMUserProgOffset(offset) (BMXDUPBA = (offset))
154+
155+// INIファイル指定キーワード(8文字以内)
156+const char InitKeywords[][9]={
157+ "106KEY","101KEY","NUMLOCK","CAPSLOCK","SCRLLOCK","WIDTH36","WIDTH48","WIDTH80"
158+};
159+unsigned char initialvmode;
160+
161+void freadline(char *s,FSFILE *fp){
162+// ファイルから1行読み込み、配列sに返す
163+// 最大8文字まで。9文字以上の場合無効
164+// #または0x20以下のコードを見つけた場合、以降は無視
165+// s:9バイト以上の配列
166+// fp:ファイルポインタ
167+ int n;
168+ char c,*p;
169+ n=0;
170+ p=s;
171+ *p=0;
172+ while(n<=8){
173+ if(FSfread(p,1,1,fp)==0 || *p=='\n'){
174+ *p=0;
175+ return;
176+ }
177+ if(*p=='#'){
178+ *p=0;
179+ break;
180+ }
181+ if(*p<=' '){
182+ if(n>0){
183+ *p=0;
184+ break;
185+ }
186+ continue;
187+ }
188+ p++;
189+ n++;
190+ }
191+ if(n>8) *s=0; //9文字以上の文字列の場合は無効
192+ //以降の文字は無視
193+ while(FSfread(&c,1,1,fp) && c!='\n') ;
194+}
195+int searchinittext(char *s){
196+// InitKeywords配列の中から文字列sを探し、位置した場合何番目かを返す
197+// 見つからなかった場合-1を返す
198+ int i;
199+ char *p1;
200+ const char *p2;
201+ for(i=0;i<sizeof(InitKeywords)/sizeof(InitKeywords[0]);i++){
202+ p1=s;
203+ p2=InitKeywords[i];
204+ while(*p1==*p2){
205+ if(*p1==0) return i;
206+ p1++;
207+ p2++;
208+ }
209+ }
210+ return -1;
211+}
212+void readinifile(void){
213+ FSFILE *fp;
214+ char inittext[9];
215+
216+ fp=FSfopen(INIFILE,"r");
217+ if(fp==NULL) return;
218+ printstr("Initialization File Found\n");
219+ lockkey=0; //INIファイルが存在する場合、Lock関連キーはINIファイルに従う
220+ while(1){
221+ if(FSfeof(fp)) break;
222+ freadline(inittext,fp);
223+ switch(searchinittext(inittext)){
224+ case 0:
225+ keytype=0;//日本語キーボード
226+ break;
227+ case 1:
228+ keytype=1;//英語キーボード
229+ break;
230+ case 2:
231+ lockkey|=2;//Num Lock
232+ break;
233+ case 3:
234+ lockkey|=4;//CAPS Lock
235+ break;
236+ case 4:
237+ lockkey|=1;//Scroll Lock
238+ break;
239+ case 5:
240+ initialvmode=VMODE_STDTEXT;
241+ break;
242+ case 6:
243+ initialvmode=VMODE_WIDETEXT;
244+ break;
245+ case 7:
246+ initialvmode=VMODE_MONOTEXT;
247+ break;
248+ }
249+ }
250+ FSfclose(fp);
251+}
252+
253+void printhex8(unsigned char d){
254+ printchar("0123456789ABCDEF"[d>>4]);
255+ printchar("0123456789ABCDEF"[d&0x0f]);
256+}
257+
258+void printhex16(unsigned short d){
259+ printhex8(d>>8);
260+ printhex8(d&0x00ff);
261+}
262+
263+void printhex32(unsigned int d){
264+ printhex16(d>>16);
265+ printhex16(d&0x0000ffff);
266+}
267+
268+int main(void){
269+ char *appname,*s;
270+
271+ /* ポートの初期設定 */
272+ CNPUB = 0xFFFF; // PORTB全てプルアップ(I/O)
273+ TRISB = 0xFFFF; // PORTB全て入力
274+ CNPUC = 0x4000; // PORTC14プルアップ(U1RX)
275+ TRISC = 0x4000; // PORTC14以外は出力
276+ TRISD = KEYSTART | KEYFIRE | KEYUP | KEYDOWN | KEYLEFT | KEYRIGHT;// ボタン接続ポート入力設定
277+ CNPUE = 0x00E0; // PORTE5-7プルアップ(I/O)
278+ TRISE = 0x00E0; // PORTE0-4出力5-7入力
279+ CNPUF = 0x0004; // PORTF2プルアップ(SDI1)
280+ TRISF = 0x0004; // PORTF2以外は出力
281+ TRISG = 0x0080; // PORTG7以外は出力
282+
283+ ANSELB = 0x0000; // 全てデジタル
284+ ANSELD = 0x0000; // 全てデジタル
285+ ANSELE = 0x0000; // 全てデジタル
286+ ANSELG = 0x0000; // 全てデジタル
287+ CNPUDSET=KEYSTART | KEYFIRE | KEYUP | KEYDOWN | KEYLEFT | KEYRIGHT;// プルアップ設定
288+ ODCF = 0x0003; //RF0,RF1はオープンドレイン
289+
290+ // 周辺機能ピン割り当て
291+ SDI2R = 1; //RPG7にSDI2を割り当て
292+ RPG8R = 6; //RPG8にSDO2を割り当て
293+
294+ // Make RAM executable. See also "char RAM[RAMSIZE]" in globalvars.c
295+ mBMXSetRAMKernProgOffset(PIC32MX_RAMSIZE-RAMSIZE);
296+ mBMXSetRAMUserDataOffset(PIC32MX_RAMSIZE);
297+ mBMXSetRAMUserProgOffset(PIC32MX_RAMSIZE);
298+
299+ init_composite(); // ビデオメモリクリア、割り込み初期化、カラービデオ出力開始
300+ setcursor(0,0,COLOR_NORMALTEXT);
301+
302+ // Show blue screen if exception before soft reset.
303+ blue_screen();
304+
305+ printstr("MachiKania BASIC System\n");
306+ printstr(" Ver "SYSVER1" "SYSVER2" by KENKEN\n");
307+ printstr("BASIC Compiler "BASVER"\n");
308+ printstr(" by Katsumi\n\n");
309+ //SDカードファイルシステム初期化
310+ setcursorcolor(COLOR_NORMALTEXT);
311+ printstr("Init File System...");
312+ // Initialize the File System
313+ if(FSInit()==FALSE){ //ファイルシステム初期化
314+ //エラーの場合停止
315+ setcursorcolor(COLOR_ERRORTEXT);
316+ printstr("\nFile System Error\n");
317+ printstr("Insert Correct Card\n");
318+ printstr("And Reset\n");
319+ while(1) asm("wait");
320+ }
321+ printstr("OK\n");
322+
323+ // 音源初期化
324+ OC4RS=LATFbits.LATF5 ? 0xff:0x00;
325+ OC3RS=LATFbits.LATF4 ? 0xff:0x00;
326+ init_music();
327+
328+ initialvmode=VMODE_STDTEXT; // 標準テキストモード(36文字)
329+ lockkey=2; // NumLockキーオン
330+ keytype=0; // 日本語キーボード
331+ readinifile(); //INIファイル読み込み
332+ printstr("Init PS/2...");
333+ wait60thsec(30); //0.5秒待ち
334+ if(ps2init()){ //PS/2初期化
335+ //キーボードが見つからない場合
336+ printstr("Keyboard Not Found\n");
337+ }
338+ else printstr("OK\n");
339+
340+ wait60thsec(60); //1秒待ち
341+
342+ set_videomode(initialvmode,0); //ビデオモード切替
343+
344+ // 実行中HEXファイル名がHEXFILEと一致した場合はエディタ起動
345+ appname=(char*)FILENAME_FLASH_ADDRESS;
346+ s=HEXFILE;
347+ while(*s++==*appname++) if(*s==0) texteditor(); //テキストエディター呼び出し
348+
349+ // 実行中HEXファイル名の「.HEX」を「.BAS」に置き換えてBASファイルを実行
350+ appname=(char*)FILENAME_FLASH_ADDRESS;
351+ s=tempfile;
352+ while(*appname!='.') *s++=*appname++;
353+ appname=".BAS";
354+ while(*appname!=0) *s++=*appname++;
355+ *s=0;
356+ // buttonmode(); //ボタン有効化
357+ g_disable_break=1; // Breakキー無効化
358+ runbasic(tempfile,0);
359+ while(1) asm(WAIT);
360+}
--- mips/trunk/megalopa/io.c (nonexistent)
+++ mips/trunk/megalopa/io.c (revision 268)
@@ -0,0 +1,651 @@
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 "compiler.h"
10+
11+/*
12+ Library functions follow
13+*/
14+static short* g_serial_buff=0;
15+static int g_serial_buff_read_pos,g_serial_buff_write_pos;
16+static int g_serial_buff_size;
17+void lib_serial(int baud, int parity, int bsize){
18+ // SERIAL x[,y[,z]]
19+ // where x is baud rate. If zero, stop using it.
20+ // y (0 is default) is parity setting; 0: 8 bit no parity,
21+ // 1: 8 bit even parity, 2: 8 bit odd parity, 3: 9 bit no parity
22+ // z is input buffer size. If z=0 (default), the size will be calculated automatically.
23+ // Calculation is: z=BAUD/10/60/2*3 (z=BAUD/400), which is 1.5 times more size required for 1/60 sec.
24+ /*
25+ RC13 U1TX RC14 U1RX
26+ U1MODE=0x0000 | (parity<<1)
27+ U1MODEbits.ON=0;
28+ U1MODEbits.FRZ=0; Continue operation when CPU is in Debug Exception mode;
29+ U1MODEbits.SIDL=0; Continue operation in Idle mode
30+ U1MODEbits.IREN=0; IrDA is disabled;
31+ U1MODEbits.RTSMD=0; UxRTS pin is in Flow Control mode
32+ U1MODEbits.UEN=0; Only UxTX and UxRX pins are enabled and used;
33+ U1MODEbits.WAKE=0; Wake-up disabled
34+ U1MODEbits.LPBACK=0; Loopback mode is disabled
35+ U1MODEbits.ABAUD=0; Baud rate measurement disabled or completed
36+ U1MODEbits.RXINV=0; UxRX Idle state is ‘1’
37+ U1MODEbits.BRGH=0; Standard Speed mode ? 16x baud clock enabled
38+ U1MODEbits.PDSEL=0-3;
39+ U1MODEbits.STSEL=0; 1 Stop bit
40+ U1STA=0x00001400;
41+ U1STAbits.ADM_EN=0; Automatic Address Detect mode is disabled
42+ U1STAbits.ADDR=0; Don't care
43+ U1STAbits.UTXISEL=0; Don't care. Don't use TX interrupt
44+ U1STAbits.UTXINV=0; UxTX Idle state is ‘1’
45+ U1STAbits.URXEN=1; UARTx receiver is enabled. UxRX pin is controlled by UARTx (if ON = 1)
46+ U1STAbits.UTXBRK=0; Break transmission is disabled or completed
47+ U1STAbits.UTXEN=1; UARTx transmitter is enabled. UxTX pin is controlled by UARTx (if ON = 1)
48+ U1STAbits.URXISEL=0; Interrupt flag bit is set when a character is received
49+ U1STAbits.ADDEN=0; Address Detect mode is disabled
50+ U1STAbits.OERR=0; Receive buffer has not overflowed
51+ U1BRG=FPB/16/baud - 1
52+ */
53+ if (baud==0) {
54+ // Disable UART
55+ U1MODE=0x0000;
56+ U1STA=0x00000000;
57+ IEC1bits.U1TXIE=0;
58+ IEC1bits.U1RXIE=0;
59+ // Free buffer area
60+ if (g_serial_buff) free_temp_str((char*)g_serial_buff);
61+ g_serial_buff=0;
62+ } else {
63+ // Prepare buffer for SERIALIN
64+ if (bsize==0) bsize=baud/400; // Area corresponds to ~1/40 sec (> 1/60 sec)
65+ g_serial_buff_size=bsize;
66+ if (g_serial_buff) free_temp_str((char*)g_serial_buff);
67+ g_serial_buff=(short*)alloc_memory((bsize+1)/2,get_permanent_var_num());
68+ g_serial_buff_read_pos=g_serial_buff_write_pos=0;
69+ // Initialize I/O ports
70+ TRISCSET=1<<14; // Input from RC14
71+ ANSELCCLR=1<<14; // Digital for RC14
72+ U1RXR=7; // Use RC14 for U1RX
73+ TRISCCLR=1<<13; // Output to RC13
74+ RPC13R=3; // Use RC13 for U1TX
75+ // Initialize UART
76+ U1MODE=0x0000 | ((parity&3)<<1);
77+ U1STA=0x00001400;
78+ U1BRG=95454533/16/baud -1;
79+ // Interrupt settings. Use only RX interrupt.
80+ IEC1bits.U1TXIE=0;
81+ IFS1bits.U1RXIF=0;
82+ IEC1bits.U1RXIE=1;
83+ IPC7bits.U1IP=3;
84+ IPC7bits.U1IS=0;
85+ // Start UART
86+ U1MODEbits.ON=1;
87+ }
88+}
89+#pragma interrupt uartint IPL3SOFT vector 31
90+void uartint(){
91+ int err;
92+ IFS1bits.U1RXIF=0;
93+ while(U1STAbits.URXDA){
94+ // Fill into the buffer while RX data is available
95+ err=0;
96+ if (U1STAbits.PERR) {
97+ if (U1MODEbits.PDSEL==1 || U1MODEbits.PDSEL==2) {
98+ // Parity error
99+ err=0x100;
100+ }
101+ }
102+ g_serial_buff[g_serial_buff_write_pos]=err|U1RXREG;
103+ g_serial_buff_write_pos++;
104+ if (g_serial_buff_size<=g_serial_buff_write_pos) g_serial_buff_write_pos=0;
105+ }
106+}
107+
108+void lib_serialout(int data){
109+ // SERIALOUT x
110+ // where x is 8 bit data. If FIFO buffer is full, wait until ready.
111+ if (U1MODEbits.PDSEL==3) {
112+ // 9 bit
113+ data&=0x1ff;
114+ } else {
115+ data&=0xff;
116+ }
117+ // Wait while buffer is full
118+ while(U1STAbits.UTXBF){
119+ asm("nop");
120+ }
121+ // Send data.
122+ U1TXREG=data;
123+}
124+int lib_serialin(int mode){
125+ int i;
126+ // SERIALIN([x])
127+ // x=0 (default): return data. If no data remaining, return -1.
128+ // x=1: If data exist(s) return 1, if not, return 0.
129+ switch(mode){
130+ case 1:
131+ // Return # of data in buffer
132+ i=g_serial_buff_write_pos-g_serial_buff_read_pos;
133+ if (i<0) i+=g_serial_buff_size;
134+ return i;
135+ case 0:
136+ default:
137+ if (g_serial_buff_write_pos==g_serial_buff_read_pos) return -1;
138+ i=g_serial_buff[g_serial_buff_read_pos];
139+ g_serial_buff_read_pos++;
140+ if (g_serial_buff_size<=g_serial_buff_read_pos) g_serial_buff_read_pos=0;
141+ return i;
142+ }
143+}
144+
145+void lib_pwm(int duty, int freq, int num){
146+ /*
147+ OCxCON=0x000D;
148+ OCxCONbits.ON=0;
149+ OCxCONbits.SIDL=0; // Continue operation in Idle mode
150+ OCxCONbits.OC32=0; // OCxR<15:0> and OCxRS<15:0> are used for comparisons to the 16-bit timer source
151+ OCxCONbits.OCFLT; // Not used
152+ OCxCONbits.OCTSEL=1; // Timer3 is the clock source for this Output Compare module
153+ OCxCONbits.OCM=5; // Initialize OCx pin low; generate continuous output pulses on OCx pin
154+
155+ Signal will be L when TMR3 reaches OCxRS, and H when TMR3 reaches OCxR
156+
157+ Timer3 prescaler: 1, 2, 4, 8, 16, 32, 64, 256
158+ For slowest Timer3 (PR3=65535), in Hz: 1456.5, 728.3, 364.1, 182.1, 91.0, 45.5, 22.8, 5.69
159+ For fastest Timer3 (PR3=1000), in Hz: 95455, 47727, 23864, 11932, 5966, 2983, 1492, 373
160+ Therefore, for freq value,
161+ 6-22: 1/256 prescaler
162+ 23-45: 1/64
163+ 46-91: 1/32
164+ 92-182: 1/16
165+ 183-364: 1/8
166+ 365-728: 1/4
167+ 729-1456: 1/2
168+ 1457-95455: 1/1
169+
170+ */
171+ static int prevfreq=0, prevPR3=0;
172+ if (num==0) {
173+ // Reset PWM
174+ prevfreq=prevPR3=0;
175+ return;
176+ }
177+ if (duty==0) {
178+ // Continuous output of L signal
179+ switch(num){
180+ case 1:
181+ // Use RD10 for digital output
182+ LATDCLR=1<<10;
183+ RPD10R=0;
184+ TRISDCLR=1<<10;
185+ return;
186+ case 2:
187+ // Use RD11 for digital output
188+ LATDCLR=1<<11;
189+ RPD11R=0;
190+ TRISDCLR=1<<11;
191+ return;
192+ default:
193+ err_invalid_param();
194+ }
195+ } else if (duty==1000) {
196+ // Continuous output of H signal
197+ switch(num){
198+ case 1:
199+ // Use RD10 for digital output
200+ LATDSET=1<<10;
201+ RPD10R=0;
202+ TRISDCLR=1<<10;
203+ return;
204+ case 2:
205+ // Use RD11 for digital output
206+ LATDSET=1<<11;
207+ RPD11R=0;
208+ TRISDCLR=1<<11;
209+ return;
210+ default:
211+ err_invalid_param();
212+ }
213+ }
214+ // PWM mode
215+ if (freq!=prevfreq || PR3!=prevPR3) {
216+ // Initialize PWM system
217+ OC3CON=0x0000;
218+ OC4CON=0x0000;
219+ IEC0bits.OC3IE=0;
220+ IEC0bits.OC4IE=0;
221+ // Stop music
222+ stop_music();
223+ // Initialize timer 3
224+ IEC0bits.T3IE=0;
225+ if (freq<6) {
226+ err_invalid_param();
227+ } else if (freq<23) {
228+ // 1/256 prescaler
229+ T3CON=0x0070;
230+ prevPR3=(int)((95454533/256)/freq)-1;
231+ } else if (freq<46) {
232+ // 1/64 prescaler
233+ T3CON=0x0060;
234+ prevPR3=(int)((95454533/64)/freq)-1;
235+ } else if (freq<92) {
236+ // 1/32 prescaler
237+ T3CON=0x0050;
238+ prevPR3=(int)((95454533/32)/freq)-1;
239+ } else if (freq<183) {
240+ // 1/16 prescaler
241+ T3CON=0x0040;
242+ prevPR3=(int)((95454533/16)/freq)-1;
243+ } else if (freq<365) {
244+ // 1/8 prescaler
245+ T3CON=0x0030;
246+ prevPR3=(int)((95454533/8)/freq)-1;
247+ } else if (freq<729) {
248+ // 1/4 prescaler
249+ T3CON=0x0020;
250+ prevPR3=(int)((95454533/4)/freq)-1;
251+ } else if (freq<1457) {
252+ // 1/2 prescaler
253+ T3CON=0x0010;
254+ prevPR3=(int)((95454533/2)/freq)-1;
255+ } else if (freq<95455) {
256+ // 1/1 prescaler
257+ T3CON=0x0000;
258+ prevPR3=(int)(95454533/freq)-1;
259+ } else {
260+ err_invalid_param();
261+ }
262+ TMR3=0;
263+ PR3=prevPR3;
264+ prevfreq=freq;
265+ }
266+ // Wait until Timer3 will reset
267+ if (T3CONbits.ON) {
268+ IFS0bits.T3IF=0;
269+ while (IFS0bits.T3IF==0);
270+ };
271+ // Stop and reset timer
272+ T3CONCLR=0x8000;
273+ TMR3=PR3;
274+ // New PWM setting follows
275+ switch(num){
276+ case 1:
277+ // Use OC3/RD10
278+ RPD10R=11;
279+ TRISDCLR=1<<10;
280+ // Disable OC3 first
281+ OC3CON=0x0000;
282+ // OC3 settings
283+ OC3CON=0x000D;
284+ OC3R=0;
285+ OC3RS=(((int)PR3+1)*duty) / 1000;
286+ // Start OC3 and timer
287+ OC3CONSET=0x8000;
288+ T3CONSET=0x8000;
289+ break;
290+ case 2:
291+ // Use OC4/RD11
292+ RPD11R=11;
293+ TRISDCLR=1<<11;
294+ // Disable OC4 first
295+ OC4CON=0x0000;
296+ // OC4 settings
297+ OC4CON=0x000D;
298+ OC4R=0;
299+ OC4RS=(((int)PR3+1)*duty) / 1000;
300+ // Wait until Timer3 will reset
301+ if (T3CONbits.ON) {
302+ IFS0bits.T3IF=0;
303+ while (IFS0bits.T3IF==0);
304+ };
305+ // Start OC4 and timer
306+ OC4CONSET=0x8000;
307+ T3CONSET=0x8000;
308+ break;
309+ default:
310+ err_invalid_param();
311+ }
312+}
313+
314+void lib_out(int pos, int val){
315+ // pos must be between 0 and 15 or 16 and 18
316+ if (0<=pos && pos<=15) {
317+ // PORTB0-15
318+ // Set output vale
319+ if (val) {
320+ LATBSET=1<<pos;
321+ } else {
322+ LATBCLR=1<<pos;
323+ }
324+ // Enable output
325+ TRISBCLR=1<<pos;
326+ // Disable pulldown
327+ CNPUBCLR=1<<pos;
328+ } else if (16<=pos && pos<=18) {
329+ // PORTE5-7, open drain
330+ pos=pos-16+5;
331+ // Set output vale (L)
332+ LATECLR=1<<pos;
333+ // Output for L and input for H
334+ if (val) {
335+ // Disable output
336+ TRISESET=1<<pos;
337+ } else {
338+ // Enable output
339+ TRISECLR=1<<pos;
340+ }
341+ } else {
342+ return;
343+ }
344+}
345+
346+void lib_out8h(int val){
347+ // Set output vale
348+ LATB=(LATB&0x00FF)|((val&0xff)<<8);
349+ // Enable output
350+ TRISBCLR=0xFF00;
351+ // Disable pulldown
352+ CNPUBCLR=0xFF00;
353+}
354+
355+void lib_out8l(int val){
356+ // Set output vale
357+ LATB=(LATB&0xFF00)|(val&0xff);
358+ // Enable output
359+ TRISBCLR=0x00FF;
360+ // Disable pulldown
361+ CNPUBCLR=0x00FF;
362+}
363+
364+int lib_out16(int val){
365+ // Set output vale
366+ LATB=(val&0xFFFF);
367+ // Enable output
368+ TRISBCLR=0xFFFF;
369+ // Disable pulldown
370+ CNPUBCLR=0xFFFF;
371+}
372+
373+int lib_in(int pos){
374+ // pos must be between 0 and 15 or 16 and 18
375+ if (0<=pos && pos<=15) {
376+ // PORTB0-15
377+ // Enable pulldown
378+ CNPUBSET=1<<pos;
379+ // Enable input
380+ TRISBSET=1<<pos;
381+ ANSELBCLR=1<<pos;
382+ // Read value and return
383+ return (PORTB&(1<<pos)) ? 1:0;
384+ } else if (16<=pos && pos<=18) {
385+ // PORTE5-7
386+ pos=pos-16+5;
387+ // Enable pulldown
388+ CNPUESET=1<<pos;
389+ // Enable input
390+ TRISESET=1<<pos;
391+ ANSELECLR=1<<pos;
392+ // Read value and return
393+ return (PORTE&(1<<pos)) ? 1:0;
394+ } else {
395+ return 0;
396+ }
397+}
398+
399+int lib_in8h(){
400+ // Enable pulldown
401+ CNPUBSET=0xFF00;
402+ // Enable input
403+ TRISBSET=0xFF00;
404+ ANSELBCLR=0xFF00;
405+ // Read value and return
406+ return (PORTB&0xFF00)>>8;
407+}
408+
409+int lib_in8l(){
410+ // Enable pulldown
411+ CNPUBSET=0x00FF;
412+ // Enable input
413+ TRISBSET=0x00FF;
414+ ANSELBCLR=0x00FF;
415+ // Read value and return
416+ return PORTB&0x00FF;
417+}
418+
419+int lib_in16(){
420+ // Enable pulldown
421+ CNPUBSET=0xFFFF;
422+ // Enable input
423+ TRISBSET=0xFFFF;
424+ ANSELBCLR=0xFFFF;
425+ // Read value and return
426+ return PORTB&0xFFFF;
427+}
428+
429+int lib_analog(int pos){
430+ /*
431+ Analog to 12 bit digital converter function.
432+ AD1CON1=0x00E0;
433+ AD1CON1bits.ON=0;
434+ AD1CON1bits.SIDL=0; // Continue module operation in Idle mode
435+ AD1CON1bits.FORM=0; // Integer 16-bit
436+ AD1CON1bits.SSRC=8; // Internal counter ends sampling and starts conversion (auto convert)
437+ AD1CON1bits.CLRASAM=0; // Normal operation, buffer contents will be overwritten by the next conversion sequence
438+ AD1CON1bits.ASAM=0; // Sampling begins when SAMP bit is set.
439+ AD1CON1bits.SAMP=0; // The ADC sample/hold amplifier is holding
440+ AD1CON1bits.DONE=0; // Analog-to-digital conversion is not done or has not started
441+ AD1CON2=0;
442+ AD1CON2bits.VCFG=0; // Voltage reference:AVdd-AVss
443+ AD1CON2bits.OFFCAL=0; // Disable Offset Calibration mode
444+ AD1CON2bits.CSCNA=0; // Do not scan inputs
445+ AD1CON2bits.BUFS=0; // Do not care, only valid when BUFM=1
446+ AD1CON2bits.SMPI=0; // Do not care. Do not use interrupt.
447+ AD1CON2bits.BUFM=0; // Buffer configured as one 16-word buffer ADC1BUFF-ADC1BUF0
448+ AD1CON2bits.ALTS=0; // Always use Sample A input multiplexer settings
449+ AD1CON3=0x0607;
450+ AD1CON3bits.ADRC=0; // Clock derived from Peripheral Bus Clock (PBCLK)
451+ AD1CON3bits.SAMC=6; // Auto-Sample Time: 6 TAD = 1005.72 ns (> 1000 ns)
452+ AD1CON3bits.ADCS=7; // TAD=TPB*2*8=167.62 ns (> 154 ns)
453+ AD1CHS=(0-27)<<16;
454+ AD1CHSbits.CN0NB=0; // Do not care, only valid when using channel B
455+ AD1CHSbits.CH0SB=0; // Do not care, only valid when using channel B
456+ AD1CHSbits.CH0NA=0; // Channel 0 negative input is VREFL
457+ AD1CHSbits.CH0SA=0-27; // Set input channel here
458+ AD1CSSL; // Do not care, only valid when CSCNA=1;
459+ */
460+ AD1CON1=0x00E0;
461+ AD1CON2=0x0000;
462+ AD1CON3=0x0607;
463+ // pos must be between 0 and 15 or 16 and 18
464+ if (0<=pos && pos<=15) {
465+ // RB0-RB15: AN0-AN15
466+ // Disable pulldown
467+ CNPUBCLR=1<<pos;
468+ // Enable input
469+ TRISBSET=1<<pos;
470+ // Enable analog
471+ ANSELBSET=1<<pos;
472+ // Select input pin
473+ AD1CHS=pos<<16;
474+ } else if (16<=pos && pos<=18) {
475+ // RE5,6,7:AN22,23,27
476+ pos=pos-16+5;
477+ // Disable pulldown
478+ CNPUECLR=1<<pos;
479+ // Enable input
480+ TRISESET=1<<pos;
481+ // Enable analog
482+ ANSELESET=1<<pos;
483+ // Select input pin
484+ if (pos<=6) {
485+ pos=pos-5+22;
486+ } else {
487+ pos=pos-7+27;
488+ }
489+ AD1CHS=pos<<16;
490+ } else {
491+ err_invalid_param();
492+ }
493+ // Enable ADC
494+ AD1CON1bits.ON=1;
495+ // Start
496+ AD1CON1bits.SAMP=1;
497+ // Wait until done
498+ while(!AD1CON1bits.DONE){
499+ asm("nop");
500+ }
501+ // Disable ADC
502+ AD1CON1bits.ON=0;
503+ // Return value
504+ return ADC1BUF0;
505+}
506+
507+/*
508+ Statements and functions implementations follow
509+*/
510+
511+// Local prototyping
512+char* param2_statement(enum libs lib);
513+
514+char* out_statement(){
515+ return param2_statement(LIB_SYSTEM | EXTRA_OUT);
516+}
517+char* out8h_statement(){
518+ char* err;
519+ err=get_value();
520+ if (err) return err;
521+ call_lib_code(LIB_SYSTEM | EXTRA_OUT8H);
522+ return 0;
523+}
524+char* out8l_statement(){
525+ char* err;
526+ err=get_value();
527+ if (err) return err;
528+ call_lib_code(LIB_SYSTEM | EXTRA_OUT8L);
529+ return 0;
530+}
531+char* out16_statement(){
532+ char* err;
533+ err=get_value();
534+ if (err) return err;
535+ call_lib_code(LIB_SYSTEM | EXTRA_OUT16);
536+ return 0;
537+}
538+char* pwm_statement(){
539+ char* err;
540+ // Get 1st parameter
541+ err=get_value();
542+ if (err) return err;
543+ check_obj_space(2);
544+ g_object[g_objpos++]=0x27BDFFF8; // addiu sp,sp,-8
545+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
546+ // Get 2nd parameter
547+ if (g_source[g_srcpos]==',') {
548+ g_srcpos++;
549+ err=get_value();
550+ if (err) return err;
551+ } else {
552+ check_obj_space(1);
553+ g_object[g_objpos++]=0x340203E8; //ori v0,zero,1000
554+ }
555+ check_obj_space(1);
556+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
557+ // Get 3rd parameter
558+ if (g_source[g_srcpos]==',') {
559+ g_srcpos++;
560+ err=get_value();
561+ if (err) return err;
562+ } else {
563+ check_obj_space(1);
564+ g_object[g_objpos++]=0x34020001; //ori v0,zero,1
565+ }
566+ // Insert calling system code
567+ call_lib_code(LIB_SYSTEM | EXTRA_PWM);
568+ check_obj_space(1);
569+ g_object[g_objpos++]=0x27BD0008; // addiu sp,sp,8
570+ return 0;
571+}
572+char* in_function(){
573+ char* err;
574+ err=get_value();
575+ if (err) return err;
576+ call_lib_code(LIB_SYSTEM | EXTRA_IN);
577+ return 0;
578+}
579+char* in8h_function(){
580+ call_lib_code(LIB_SYSTEM | EXTRA_IN8H);
581+ return 0;
582+}
583+char* in8l_function(){
584+ call_lib_code(LIB_SYSTEM | EXTRA_IN8L);
585+ return 0;
586+}
587+char* in16_function(){
588+ call_lib_code(LIB_SYSTEM | EXTRA_IN16);
589+ return 0;
590+}
591+char* analog_function(){
592+ char* err;
593+ err=get_value();
594+ if (err) return err;
595+ call_lib_code(LIB_SYSTEM | EXTRA_ANALOG);
596+ return 0;
597+}
598+char* serial_statement(){
599+ char* err;
600+ // Get 1st parameter
601+ err=get_value();
602+ if (err) return err;
603+ check_obj_space(2);
604+ g_object[g_objpos++]=0x27BDFFF8; // addiu sp,sp,-8
605+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
606+ // Get 2nd parameter
607+ if (g_source[g_srcpos]==',') {
608+ g_srcpos++;
609+ err=get_value();
610+ if (err) return err;
611+ } else {
612+ check_obj_space(1);
613+ g_object[g_objpos++]=0x34020000; //ori v0,zero,0000
614+ }
615+ check_obj_space(1);
616+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
617+ // Get 3rd parameter
618+ if (g_source[g_srcpos]==',') {
619+ g_srcpos++;
620+ err=get_value();
621+ if (err) return err;
622+ } else {
623+ check_obj_space(1);
624+ g_object[g_objpos++]=0x34020000; //ori v0,zero,0
625+ }
626+ // Insert calling system code
627+ call_lib_code(LIB_SYSTEM | EXTRA_SERIAL);
628+ check_obj_space(1);
629+ g_object[g_objpos++]=0x27BD0008; // addiu sp,sp,8
630+ return 0;
631+}
632+char* serialout_statement(){
633+ char* err;
634+ err=get_value();
635+ if (err) return err;
636+ call_lib_code(LIB_SYSTEM | EXTRA_SERIALOUT);
637+ return 0;
638+}
639+char* serialin_function(){
640+ char* err;
641+ next_position();
642+ if (g_source[g_srcpos]==')') {
643+ check_obj_space(1);
644+ g_object[g_objpos++]=0x34020000; //ori v0,zero,0000
645+ } else {
646+ err=get_value();
647+ if (err) return err;
648+ }
649+ call_lib_code(LIB_SYSTEM | EXTRA_SERIALIN);
650+ return 0;
651+}
--- mips/trunk/megalopa/main.h (nonexistent)
+++ mips/trunk/megalopa/main.h (revision 268)
@@ -0,0 +1,22 @@
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 MEGALOPA
9+#define SYSVER1 "Megalopa"
10+#define SYSVER2 "1.0"
11+#define BASVER "KM-1300"
12+
13+#define INIFILE "MACHIKAM.INI" // 初期設定ファイル
14+#define HEXFILE "MACHIKAM.HEX" // 実行中HEXファイル名がこれと一致した場合はエディタ起動
15+
16+#define FILENAME_FLASH_ADDRESS 0x9D07EFF0
17+#define PIC32MX_RAMSIZE 0x20000
18+#define PIC32MX_FLASHSIZE 0x80000
19+
20+void printhex8(unsigned char d);
21+void printhex16(unsigned short d);
22+void printhex32(unsigned int d);
--- mips/trunk/megalopa/music.c (nonexistent)
+++ mips/trunk/megalopa/music.c (revision 268)
@@ -0,0 +1,902 @@
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+ Tone data for 15700 Hz sampling frequency,
14+ supporting 3.4 Hz - 440 Hz - 31400 Hz,
15+ are 2147483647 - 16777216 (2^24) - 235095, respectively.
16+ The counter for DMA is working 470189 times more than the actual clock.
17+ Therefore, 440 Hz correspond to 16777216 (= 470189 * 15700/440) counts of this timer.
18+
19+ Example:
20+ When producing 440 Hz signal, the timer (initially set to 16777216) will be decreased
21+ by 470189 at 15700 Hz frequency. When the timer will be equal to or less than half of
22+ 16777216 (8388608), toggle output. When the timer will be zero or negative, toggle
23+ output and add 16777216 to timer.
24+*/
25+
26+/*
27+ c 14107904
28+ B 14946809
29+ A# 15835575
30+ A 16777216
31+ G# 17774828
32+ G 18831809
33+ F# 19951607
34+ F 21137982
35+ E 22394866
36+ D# 23726565
37+ D 25137402
38+ C# 26632135
39+ C 28215755
40+ Cb 29893558
41+*/
42+
43+const static int g_keys[]={
44+ 15835575,14107904,26632135,23726565,21137982,19951607,17774828,// 0 7# C# A#m
45+ 15835575,14946809,26632135,23726565,21137982,19951607,17774828,// 7 6# F# D#m
46+ 15835575,14946809,26632135,23726565,22394866,19951607,17774828,// 14 5# B G#m
47+ 16777216,14946809,26632135,23726565,22394866,19951607,17774828,// 21 4# E C#m
48+ 16777216,14946809,26632135,25137402,22394866,19951607,17774828,// 28 3# A F#m
49+ 16777216,14946809,26632135,25137402,22394866,19951607,18831809,// 35 2# D Bm
50+ 16777216,14946809,28215755,25137402,22394866,19951607,18831809,// 42 1# G Em
51+ 16777216,14946809,28215755,25137402,22394866,21137982,18831809,// 49 0 C Am
52+ 16777216,15835575,28215755,25137402,22394866,21137982,18831809,// 56 1b F Dm
53+ 16777216,15835575,28215755,25137402,23726565,21137982,18831809,// 63 2b Bb Gm
54+ 17774828,15835575,28215755,25137402,23726565,21137982,18831809,// 70 3b Eb Cm
55+ 17774828,15835575,28215755,26632135,23726565,21137982,18831809,// 77 4b Ab Fm
56+ 17774828,15835575,28215755,26632135,23726565,21137982,19951607,// 84 5b Db Bbm
57+ 17774828,15835575,29893558,26632135,23726565,21137982,19951607,// 91 6b Gb Ebm
58+ 17774828,15835575,29893558,26632135,23726565,22394866,19951607,// 98 7b Cb Abm
59+};
60+
61+/*
62+ 2^(1/12) ~= 1+1/16-1/256
63+ 1/(2^(1/12)) ~= 1-1/16+1/128-1/512
64+*/
65+
66+#define toneFlat(x) ((x)+((x)>>4)-((x)>>8))
67+#define toneSharp(x) ((x)-((x)>>4)+((x)>>7)-((x)>>9))
68+
69+/* local global vars */
70+static int* g_tones;
71+static int g_qvalue;
72+static int g_lvalue;
73+static int g_mpoint;
74+static char* g_mstr;
75+static int g_mspos;
76+static int g_musicL[32];
77+static int g_soundL[32];
78+static unsigned short g_musiclenL[32];
79+static unsigned char g_soundlenL[32];
80+static int g_musicstartL;
81+static int g_musicendL;
82+static int g_musicwaitL;
83+static int g_soundstartL;
84+static int g_soundendL;
85+static int g_soundwaitL;
86+static int g_soundrepeatL;
87+static int g_musicR[32];
88+static int g_soundR[32];
89+static unsigned short g_musiclenR[32];
90+static unsigned char g_soundlenR[32];
91+static int g_musicstartR;
92+static int g_musicendR;
93+static int g_musicwaitR;
94+static int g_soundstartR;
95+static int g_soundendR;
96+static int g_soundwaitR;
97+static int g_soundrepeatR;
98+
99+#define MFLAG_L 2
100+#define MFLAG_R 1
101+
102+static char g_sound_mode=0;
103+static FSFILE* g_fhandle=0;
104+static unsigned char* wavtable=0;
105+static int wave_stereo;
106+#define wave_sector_size (wave_stereo ? 524 : 262)
107+
108+#define SOUND_MODE_NONE 0
109+#define SOUND_MODE_MUSIC 1
110+#define SOUND_MODE_WAVE 2
111+
112+#define start_wavedma() T4CONSET=0x8000; DCH1CONSET=DCH2CONSET=0x00000080
113+#define stop_wavedma() T4CONCLR=0x8000; DCH1CONCLR=DCH2CONCLR=0x00000080; g_sound_mode=SOUND_MODE_NONE
114+
115+void init_wave_dma();
116+
117+int musicRemaining(int flagsLR){
118+ int l, r;
119+ l=(g_musicendL-g_musicstartL)&31;
120+ r=(g_musicendL-g_musicstartL)&31;
121+ if (flagsLR & MFLAG_L) return l;
122+ if (flagsLR & MFLAG_R) return r;
123+ return (l>r) ? l:r;
124+}
125+
126+int waveRemaining(int mode){
127+ int ret;
128+ if (!g_fhandle) return 0;
129+ switch(mode){
130+ case 1: // current position (header excluded)
131+ ret=g_fhandle->seek-0x2c;
132+ break;
133+ case 2: // file size (header excluded)
134+ ret=g_fhandle->size-0x2c;
135+ break;
136+ case 0: // remaining
137+ default:
138+ ret=g_fhandle->size-g_fhandle->seek;
139+ break;
140+ }
141+ if (wave_stereo) ret=ret>>1;
142+ return ret;
143+}
144+
145+#pragma interrupt musicint IPL2SOFT vector 1
146+void musicint(){
147+ static unsigned short wavtable_pos;
148+ static int music_freq_L=0;
149+ static int music_timer_L=0;
150+ static int music_freq_R=0;
151+ static int music_timer_R=0;
152+ unsigned int i,j;
153+ // This function is called every 1/60 sec.
154+ IFS0bits.CS0IF=0;
155+ switch(g_sound_mode){
156+ case SOUND_MODE_WAVE:
157+ // Initialize parameters
158+ if (!T4CONbits.ON){
159+ wavtable_pos=0;
160+ music_timer_L=music_timer_R=0;
161+ start_wavedma();
162+ }
163+ wavtable_pos=wave_sector_size-wavtable_pos;
164+ // Read from file
165+ if (0 == FSfread((void*)&wavtable[wavtable_pos],1,wave_sector_size,g_fhandle)) {
166+ // End of file.
167+ stop_wavedma();
168+ FSfclose(g_fhandle);
169+ g_fhandle=0;
170+ g_sound_mode=SOUND_MODE_NONE;
171+ stop_music();
172+ break;
173+ }
174+ // Continue to MUSIC sound mode
175+ case SOUND_MODE_MUSIC:
176+ // Left sound/music
177+ if (g_soundstartL!=g_soundendL){
178+ // Start timer
179+ music_freq_L=g_soundL[g_soundstartL];
180+ if ((--g_soundwaitL)<=0) {
181+ g_soundstartL++;
182+ if (g_soundstartL==g_soundendL || 31<g_soundstartL) {
183+ g_soundstartL=0;
184+ g_soundrepeatL--;
185+ if (0<g_soundrepeatL) {
186+ g_soundwaitL=g_soundlenL[g_soundstartL];
187+ } else {
188+ g_soundendL=g_soundrepeatL=g_soundwaitL=0;
189+ }
190+ } else {
191+ g_soundwaitL=g_soundlenL[g_soundstartL];
192+ }
193+ }
194+ // Shift music data even though without output.
195+ if (g_musicstartL!=g_musicendL) {
196+ if ((--g_musicwaitL)<=0) {
197+ g_musicstartL++;
198+ g_musicstartL&=31;
199+ g_musicwaitL=g_musiclenL[g_musicstartL];
200+ }
201+ }
202+ } else if (g_musicstartL!=g_musicendL) {
203+ // Start timer
204+ music_freq_L=g_musicL[g_musicstartL];
205+ if ((--g_musicwaitL)<=0) {
206+ g_musicstartL++;
207+ g_musicstartL&=31;
208+ g_musicwaitL=g_musiclenL[g_musicstartL];
209+ }
210+ } else {
211+ music_freq_L=0;
212+ }
213+ // Right sound/music
214+ if (g_soundstartR!=g_soundendR){
215+ // Start timer
216+ music_freq_R=g_soundR[g_soundstartR];
217+ if ((--g_soundwaitR)<=0) {
218+ g_soundstartR++;
219+ if (g_soundstartR==g_soundendR || 31<g_soundstartR) {
220+ g_soundstartR=0;
221+ g_soundrepeatR--;
222+ if (0<g_soundrepeatR) {
223+ g_soundwaitR=g_soundlenR[g_soundstartR];
224+ } else {
225+ g_soundendR=g_soundrepeatR=g_soundwaitR=0;
226+ }
227+ } else {
228+ g_soundwaitR=g_soundlenR[g_soundstartR];
229+ }
230+ }
231+ // Shift music data even though without output.
232+ if (g_musicstartR!=g_musicendR) {
233+ if ((--g_musicwaitR)<=0) {
234+ g_musicstartR++;
235+ g_musicstartR&=31;
236+ g_musicwaitR=g_musiclenR[g_musicstartR];
237+ }
238+ }
239+ } else if (g_musicstartR!=g_musicendR) {
240+ // Start timer
241+ music_freq_R=g_musicR[g_musicstartR];
242+ if ((--g_musicwaitR)<=0) {
243+ g_musicstartR++;
244+ g_musicstartR&=31;
245+ g_musicwaitR=g_musiclenR[g_musicstartR];
246+ }
247+ } else {
248+ music_freq_R=0;
249+ }
250+ // music_freq_L/R is controlling music/sound.
251+ // If this value is valid, make sound with this frequency
252+ if (g_sound_mode!=SOUND_MODE_WAVE) {
253+ if (!T4CONbits.ON){
254+ // Initialize parameters
255+ wavtable_pos=0;
256+ music_timer_L=music_timer_R=0;
257+ start_wavedma();
258+ // Silent in the first sector
259+ for(i=0;i<wave_sector_size;i++) wavtable[i]=0x80;
260+ }
261+ wavtable_pos=wave_sector_size-wavtable_pos;
262+ }
263+ // Modify WAVE table (SOUND_MODE_WAVE) or construct WAVE table (SOUND_MODE_MUSIC)
264+ if (g_sound_mode==SOUND_MODE_WAVE && music_freq_L==0 && music_freq_R==0) {
265+ // Modification is not needed
266+ break;
267+ }
268+ for(i=0;i<wave_sector_size;i++){
269+ if (music_freq_L) {
270+ music_timer_L-=470189;
271+ if (music_timer_L<=0) {
272+ music_timer_L+=music_freq_L;
273+ j=0xc0;
274+ } else if (music_timer_L<=(music_freq_L>>1)) {
275+ j=0x40;
276+ } else {
277+ j=0xc0;
278+ }
279+ } else {
280+ j=0x80;
281+ }
282+ if (g_sound_mode==SOUND_MODE_WAVE) {
283+ // In WAVE mode, MUSIC/SOUND data is added to WAVE data
284+ j-=0x80;
285+ j+=wavtable[wavtable_pos+i];
286+ if (j<0x00) j=0;
287+ else if (0xff<j) j=0xff;
288+ wavtable[wavtable_pos+i]=j;
289+ } else {
290+ // In MUSIC mode, MUSIC/SOUND data is newly created
291+ wavtable[wavtable_pos+i]=j;
292+ }
293+ if (music_freq_R) {
294+ music_timer_R-=470189;
295+ if (music_timer_R<=0) {
296+ music_timer_R+=music_freq_R;
297+ j=0xc0;
298+ } else if (music_timer_R<=(music_freq_R>>1)) {
299+ j=0x40;
300+ } else {
301+ j=0xc0;
302+ }
303+ } else {
304+ j=0x80;
305+ }
306+ if (wave_stereo) {
307+ if (g_sound_mode==SOUND_MODE_WAVE) {
308+ // In WAVE mode, MUSIC/SOUND data is added to WAVE data
309+ j-=0x80;
310+ j+=wavtable[wavtable_pos+i+1];
311+ if (j<0x00) j=0;
312+ else if (0xff<j) j=0xff;
313+ wavtable[wavtable_pos+i+1]=j;
314+ } else {
315+ wavtable[wavtable_pos+i+1]=j;
316+ // In MUSIC mode, MUSIC/SOUND data is newly created
317+ }
318+ // Increment i here and in if statement (total addition 2 for stereo mode)
319+ i++;
320+ }
321+ }
322+ break;
323+ case SOUND_MODE_NONE:
324+ music_freq_L=0;
325+ music_timer_L=0;
326+ music_freq_R=0;
327+ music_timer_R=0;
328+ // Move OC3RS and OC4RS to 0x80 if less or more.
329+ if (OC3RS<0x80) {
330+ OC3RS++;
331+ } else if (0x80<OC3RS) {
332+ OC3RS--;
333+ }
334+ if (OC4RS<0x80) {
335+ OC4RS++;
336+ } else if (0x80<OC4RS) {
337+ OC4RS--;
338+ }
339+ if (OC3RS==0x80 && OC4RS==0x80) {
340+ // Stop interrupt
341+ IEC0bits.CS0IE=0;
342+ }
343+ break;
344+ default:
345+ break;
346+ }
347+}
348+
349+int musicGetNum(){
350+ int i, ret;
351+ char b;
352+ // Skip non number character
353+ for(i=0;(b=g_mstr[g_mspos+i])<'0' && '9'<g_mstr[g_mspos+i];i++);
354+ // Determine the number
355+ ret=0;
356+ while('0'<=b && b<='9'){
357+ ret*=10;
358+ ret+=b-'0';
359+ i++;
360+ b=g_mstr[g_mspos+i];
361+ }
362+ g_mspos+=i;
363+ return ret;
364+}
365+
366+static const unsigned int inv_rf4[1]={0x00000010};
367+static const unsigned int inv_rf5[1]={0x00000020};
368+
369+void init_normal_music(){
370+ // Use Timer3 and DMA2 for left (RF5)
371+ // Use Timer4 and DMA1 for right (RF4)
372+ stop_music();
373+
374+ // Alocate 524*2 byte buffer if not assigned
375+ if (g_var_size[ALLOC_WAVE_BLOCK]==0) {
376+ wavtable=(char*)alloc_memory(524*2/4,ALLOC_WAVE_BLOCK);
377+ }
378+
379+ // Set music mode
380+ g_sound_mode=SOUND_MODE_MUSIC;
381+ wave_stereo=1;
382+
383+ // DMA setting
384+ init_wave_dma();
385+
386+ // Software interrupt every 1/60 sec (triggered by Timer2)
387+ IFS0bits.CS0IF=0;
388+ IEC0bits.CS0IE=1;
389+}
390+
391+void init_music(){
392+ // Currently this function is called in main.c and run.c
393+ stop_music();
394+
395+ // Initializations for music/sound.
396+ g_qvalue=160; // Q: 1/4=90
397+ g_lvalue=20; // L: 1/8
398+ g_tones=(int*)&(g_keys[49]); // C major
399+ g_musicstartL=g_musicendL=g_musicwaitL=g_soundstartL=g_soundendL=g_soundwaitL=g_soundrepeatL=0;
400+ g_musicstartR=g_musicendR=g_musicwaitR=g_soundstartR=g_soundendR=g_soundwaitR=g_soundrepeatR=0;
401+
402+ // Timer3 for PWM
403+ T3CON=0x0000;
404+ PR3=0x100;
405+ TMR3=0;
406+
407+ // OC4 setting
408+ RPF5R = 0x0b; //Use RPF5 for OC4
409+ if (OC4RS&0xff00) OC4RS=0x00;
410+ OC4CON=0x000e;
411+ OC4CONSET=0x8000;
412+ // OC3 setting
413+ RPF4R = 0x0b; //Use RPF4 for OC3
414+ if (OC3RS&0xff00) OC3RS=0x00;
415+ OC3CON=0x000e;
416+ OC3CONSET=0x8000;
417+
418+ // Start timer3
419+ T3CON=0x8000;
420+
421+ // Move OC4RS and OC3 RS from 0x00 to 0x80
422+ g_sound_mode=SOUND_MODE_NONE;
423+ // Enable interrupt
424+ IPC0bits.CS0IP=2;
425+ IPC0bits.CS0IS=0;
426+ IFS0bits.CS0IF=0;
427+ IEC0bits.CS0IE=1;
428+}
429+
430+void musicSetL(){
431+ // Set length of a character.
432+ // Syntax: L:n/m, where n and m are numbers.
433+ int n,m;
434+ n=musicGetNum();
435+ g_mspos++;
436+ m=musicGetNum();
437+ g_lvalue=g_qvalue*n/m;
438+}
439+
440+void musicSetQ(){
441+ int i;
442+ // Syntax: Q:1/4=n, where n is number.
443+ // Skip "1/4="
444+ for(i=0;g_mstr[g_mspos+i]!='=';i++);
445+ g_mspos+=i+1;
446+ i=musicGetNum();
447+ if (i<48) { g_qvalue=320; /* 1/4=45 */ }
448+ else if (i<53) { g_qvalue=288; /* 1/4=50 */ }
449+ else if (i<60) { g_qvalue=256; /* 1/4=56 */ }
450+ else if (i<70) { g_qvalue=224; /* 1/4=64 */ }
451+ else if (i<83) { g_qvalue=192; /* 1/4=75 */ }
452+ else if (i<102) { g_qvalue=160; /* 1/4=90 */ }
453+ else if (i<132) { g_qvalue=128; /* 1/4=113 */ }
454+ else if (i<188) { g_qvalue=96; /* 1/4=150 */ }
455+ else { g_qvalue=64; /* 1/4=225 */ }
456+ g_lvalue=g_qvalue>>3;
457+}
458+
459+void musicSetK(){
460+ // Syntax: K:xxx
461+ if (!strncmp((char*)&(g_mstr[g_mspos]),"A#m",3)) {
462+ g_mspos+=3;
463+ g_tones=(int*)&(g_keys[0]);
464+ return;
465+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"D#m",3)) {
466+ g_mspos+=3;
467+ g_tones=(int*)&(g_keys[7]);
468+ return;
469+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"G#m",3)) {
470+ g_mspos+=3;
471+ g_tones=(int*)&(g_keys[14]);
472+ return;
473+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"C#m",3)) {
474+ g_mspos+=3;
475+ g_tones=(int*)&(g_keys[21]);
476+ return;
477+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"F#m",3)) {
478+ g_mspos+=3;
479+ g_tones=(int*)&(g_keys[28]);
480+ return;
481+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Bbm",3)) {
482+ g_mspos+=3;
483+ g_tones=(int*)&(g_keys[84]);
484+ return;
485+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Ebm",3)) {
486+ g_mspos+=3;
487+ g_tones=(int*)&(g_keys[91]);
488+ return;
489+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Abm",3)) {
490+ g_mspos+=3;
491+ g_tones=(int*)&(g_keys[98]);
492+ return;
493+ }
494+ if (!strncmp((char*)&(g_mstr[g_mspos]),"C#",2)) {
495+ g_mspos+=2;
496+ g_tones=(int*)&(g_keys[0]);
497+ return;
498+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"F#",2)) {
499+ g_mspos+=2;
500+ g_tones=(int*)&(g_keys[7]);
501+ return;
502+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Bm",2)) {
503+ g_mspos+=2;
504+ g_tones=(int*)&(g_keys[35]);
505+ return;
506+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Em",2)) {
507+ g_mspos+=2;
508+ g_tones=(int*)&(g_keys[42]);
509+ return;
510+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Am",2)) {
511+ g_mspos+=2;
512+ g_tones=(int*)&(g_keys[49]);
513+ return;
514+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Dm",2)) {
515+ g_mspos+=2;
516+ g_tones=(int*)&(g_keys[56]);
517+ return;
518+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Gm",2) || !strncmp((char*)&(g_mstr[g_mspos]),"Bb",2)) {
519+ g_mspos+=2;
520+ g_tones=(int*)&(g_keys[63]);
521+ return;
522+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Cm",2) || !strncmp((char*)&(g_mstr[g_mspos]),"Eb",2)) {
523+ g_mspos+=2;
524+ g_tones=(int*)&(g_keys[70]);
525+ return;
526+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Fm",2) || !strncmp((char*)&(g_mstr[g_mspos]),"Ab",2)) {
527+ g_mspos+=2;
528+ g_tones=(int*)&(g_keys[77]);
529+ return;
530+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Db",2)) {
531+ g_mspos+=2;
532+ g_tones=(int*)&(g_keys[84]);
533+ return;
534+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Gb",2)) {
535+ g_mspos+=2;
536+ g_tones=(int*)&(g_keys[91]);
537+ return;
538+ } else if (!strncmp((char*)&(g_mstr[g_mspos]),"Cb",2)) {
539+ g_mspos+=2;
540+ g_tones=(int*)&(g_keys[98]);
541+ return;
542+ }
543+ switch(g_mstr[g_mspos]){
544+ case 'B':
545+ g_mspos++;
546+ g_tones=(int*)&(g_keys[14]);
547+ return;
548+ case 'E':
549+ g_mspos++;
550+ g_tones=(int*)&(g_keys[21]);
551+ return;
552+ case 'A':
553+ g_mspos++;
554+ g_tones=(int*)&(g_keys[28]);
555+ return;
556+ case 'D':
557+ g_mspos++;
558+ g_tones=(int*)&(g_keys[35]);
559+ return;
560+ case 'G':
561+ g_mspos++;
562+ g_tones=(int*)&(g_keys[42]);
563+ return;
564+ case 'C':
565+ g_mspos++;
566+ g_tones=(int*)&(g_keys[49]);
567+ return;
568+ case 'F':
569+ g_mspos++;
570+ g_tones=(int*)&(g_keys[56]);
571+ return;
572+ default:
573+ err_music(g_mstr);
574+ break;
575+ }
576+}
577+void musicSetM(){
578+ // Currently do nothing
579+ musicGetNum();
580+ musicGetNum();
581+}
582+
583+void set_sound(unsigned long* data, int flagsLR){
584+ int sound;
585+ int len;
586+ int pos;
587+ int datalen;
588+ if (g_sound_mode==SOUND_MODE_NONE) {
589+ // Start normal music mode
590+ init_normal_music();
591+ }
592+ IEC0bits.CS0IE=0; // Stop interruption, first.
593+ // Initialize
594+ if (flagsLR & MFLAG_L) g_soundrepeatL=g_soundstartL=g_soundendL=0;
595+ if (flagsLR & MFLAG_R) g_soundrepeatR=g_soundstartR=g_soundendR=0;
596+ pos=0;
597+ do {
598+ while(data[1]!=0x00000020) data++; // Seek DATA statement
599+ datalen=(data[0]&0x00007FFF)-1; // Use bgezal statement containing data length.
600+ data+=2;
601+ while(0<datalen){
602+ datalen--;
603+ len=data[0]>>16;
604+ sound=data[0]&0x0000FFFF;
605+ data++;
606+ if (len) {
607+ // Shift tone for 2048 <--> ~440 Hz.
608+ // 2048 = 2^11
609+ // 16777216 = 2^24
610+ sound=sound<<13;
611+ if (flagsLR & MFLAG_L) g_soundL[pos]=sound;
612+ if (flagsLR & MFLAG_R) g_soundR[pos]=sound;
613+ if (flagsLR & MFLAG_L) g_soundlenL[pos]=len;
614+ if (flagsLR & MFLAG_R) g_soundlenR[pos]=len;
615+ pos++;
616+ if (32<pos) {
617+ err_music("Sound data too long.");
618+ return;
619+ }
620+ } else {
621+ if (flagsLR & MFLAG_L) g_soundrepeatL=sound;
622+ if (flagsLR & MFLAG_R) g_soundrepeatR=sound;
623+ break;
624+ }
625+ }
626+ } while(len);
627+ if (flagsLR & MFLAG_L) g_soundendL=pos;
628+ if (flagsLR & MFLAG_R) g_soundendR=pos;
629+ if (flagsLR & MFLAG_L) g_soundwaitL=g_soundlenL[0];
630+ if (flagsLR & MFLAG_R) g_soundwaitR=g_soundlenR[0];
631+ IEC0bits.CS0IE=1; // Restart interrupt.
632+}
633+
634+void set_music(char* str, int flagsLR){
635+ char b;
636+ unsigned long tone,tonenatural;
637+ int len;
638+ if (g_sound_mode==SOUND_MODE_NONE) {
639+ // Start normal music mode
640+ init_normal_music();
641+ }
642+ g_mstr=str;
643+ g_mspos=0;
644+ while(0<(b=g_mstr[g_mspos])){
645+ if (g_mstr[g_mspos+1]==':') {
646+ // Set property
647+ g_mspos+=2;
648+ switch(b){
649+ case 'L':
650+ musicSetL();
651+ break;
652+ case 'Q':
653+ musicSetQ();
654+ break;
655+ case 'K':
656+ musicSetK();
657+ break;
658+ case 'M':
659+ musicSetM();
660+ break;
661+ default:
662+ err_music(str);
663+ break;
664+ }
665+ } else if ('A'<=b && b<='G' || 'a'<=b && b<='g' || b=='z') {
666+ g_mspos++;
667+ if (b=='z') {
668+ tone=0;
669+ } else if (b<='G') {
670+ tone=g_tones[b-'A'];
671+ tonenatural=g_keys[b-'A'+49];
672+ } else {
673+ tone=g_tones[b-'a']>>1;
674+ tonenatural=g_keys[b-'a'+49]>>1;
675+ }
676+ // Check "'"s
677+ while(g_mstr[g_mspos]=='\''){
678+ g_mspos++;
679+ tone>>=1;
680+ }
681+ // Check ","s
682+ while(g_mstr[g_mspos]==','){
683+ g_mspos++;
684+ tone<<=1;
685+ tonenatural<<=1;
686+ }
687+ // Check "^","=","_"
688+ switch(g_mstr[g_mspos]){
689+ case '^':
690+ g_mspos++;
691+ tone=toneSharp(tone);
692+ break;
693+ case '_':
694+ g_mspos++;
695+ tone=toneFlat(tone);
696+ break;
697+ case '=':
698+ g_mspos++;
699+ tone=tonenatural;
700+ break;
701+ default:
702+ break;
703+ }
704+ // Check number for length
705+ b=g_mstr[g_mspos];
706+ if ('0'<=b && b<='9') {
707+ len=g_lvalue*musicGetNum();
708+ } else {
709+ len=g_lvalue;
710+ }
711+ if (g_mstr[g_mspos]=='/') {
712+ g_mspos++;
713+ len=len/musicGetNum();
714+ }
715+ // Update music value array
716+ IEC0bits.CS0IE=0; // Stop interruption, first.
717+ // Update left music
718+ if (flagsLR & MFLAG_L) {
719+ if (g_musicstartL==g_musicendL) {
720+ g_musicwaitL=len;
721+ }
722+ g_musicL[g_musicendL]=tone;
723+ g_musiclenL[g_musicendL]=len;
724+ g_musicendL++;
725+ g_musicendL&=31;
726+ }
727+ // Update right music
728+ if (flagsLR & MFLAG_R) {
729+ if (g_musicstartR==g_musicendR) {
730+ g_musicwaitR=len;
731+ }
732+ g_musicR[g_musicendR]=tone;
733+ g_musiclenR[g_musicendR]=len;
734+ g_musicendR++;
735+ g_musicendR&=31;
736+ }
737+ IEC0bits.CS0IE=1; // Restart interruption.
738+ } else {
739+ err_music(str);
740+ }
741+ // Go to next character
742+ while(0<g_mstr[g_mspos] && g_mstr[g_mspos]<=0x20 || g_mstr[g_mspos]=='|') g_mspos++;
743+ }
744+}
745+
746+/*
747+ In WAVE mode (for both stereo and monaural):
748+ DMA2/OC4 is used for left
749+ DMA1/OC3 is used for right
750+ Timer 3 is used for PWM for both L/R
751+ Timer 4 is used for both DMA1/DMA2
752+*/
753+
754+int checkChars(char* str1, char* str2, int num){
755+ int i;
756+ for(i=0;i<num;i++){
757+ if (str1[i]!=str2[i]) return 1;
758+ }
759+ return 0;
760+}
761+
762+FSFILE* openWave(char* file){
763+ FSFILE *fp;
764+ int i;
765+
766+ // Open Wave file
767+ fp=FSfopen(file,"r");
768+ if(fp==NULL) err_file();
769+
770+ // Read the header
771+ if (0x2c != FSfread((void*)&wavtable[0],1,0x2c,fp)) {
772+ err_wave();
773+ }
774+ i=0;
775+ i+=checkChars((char*)&wavtable[0],"RIFF",4); // Check RIFF
776+ i+=checkChars((char*)&wavtable[8],"WAVEfmt ",8); // Check WAVE and fmt
777+ i+=checkChars((char*)&wavtable[16],"\x10\x00\x00\x00\x01\x00",6); // Check if liear PCM
778+ if (!checkChars((char*)&wavtable[22],"\x02\x00\x80\x3e\x00\x00\x00\x7d\x00\x00\x02\x00",12)) {
779+ // Stereo 16000 Hz
780+ wave_stereo=1;
781+ } else if (!checkChars((char*)&wavtable[22],"\x01\x00\x80\x3e\x00\x00\x80\x3e\x00\x00\x01\x00",12)) {
782+ // Monaural 16000 Hz
783+ wave_stereo=0;
784+ } else if (!checkChars((char*)&wavtable[22],"\x02\x00\x54\x3d\x00\x00\xa8\x7a\x00\x00\x02\x00",12)) {
785+ // Stereo 15700 Hz
786+ wave_stereo=1;
787+ } else if (!checkChars((char*)&wavtable[22],"\x01\x00\x54\x3d\x00\x00\x54\x3d\x00\x00\x01\x00",12)) {
788+ // Monaural 15700 Hz
789+ wave_stereo=0;
790+ } else {
791+ i=1;
792+ }
793+ i+=checkChars((char*)&wavtable[34],"\x08\x00\x64\x61\x74\x61",6); // Check bit # and data
794+ if (i) {
795+ err_wave();
796+ }
797+ return fp;
798+}
799+
800+void init_wave_dma(){
801+ // Timer4 for 15700 Hz
802+ TMR4=0;
803+ PR4=6080-1;
804+ TMR4=PR4-1;
805+ T4CON=0x0000; // Not start yet
806+
807+ if (wave_stereo) {
808+ //DMA2 settings for OC4 for left
809+ DMACONSET=0x8000;
810+ DCH2CON=0x00000012; // CHBUSY=0, CHCHNS=0, CHEN=0, CHAED=0, CHCHN=0, CHAEN=1, CHEDET=0, CHPRI=b10
811+ DCH2ECON=0x1310; // CHAIRQ=0, CHSIRQ=19, CFORCE=0, CABRT=0, PATEN=0, SIRQEN=1, AIRQEN=0
812+ // CHSIRQ=19: Timer4 interrupt
813+ DCH2SSA=((unsigned int)&(wavtable[-1]))&0x1fffffff;
814+ DCH2DSA=0x1F803620-1; // OC4RS
815+ DCH2SSIZ=524*2;
816+ DCH2DSIZ=2;
817+ DCH2CSIZ=2;
818+ DCH2INTCLR=0x00FF00FF;
819+ DCH2CONSET=0x00000080;
820+
821+ //DMA1 settings for OC3 for rifht
822+ DMACONSET=0x8000;
823+ DCH1CON=0x00000012; // CHBUSY=0, CHCHNS=0, CHEN=0, CHAED=0, CHCHN=0, CHAEN=1, CHEDET=0, CHPRI=b10
824+ DCH1ECON=0x1310; // CHAIRQ=0, CHSIRQ=19, CFORCE=0, CABRT=0, PATEN=0, SIRQEN=1, AIRQEN=0
825+ // CHSIRQ=19: Timer4 interrupt
826+ DCH1SSA=((unsigned int)&(wavtable[0]))&0x1fffffff;
827+ DCH1DSA=0x1F803420-1; // OC3RS
828+ DCH1SSIZ=524*2;
829+ DCH1DSIZ=2;
830+ DCH1CSIZ=2;
831+ DCH1INTCLR=0x00FF00FF;
832+ DCH1CONSET=0x00000080;
833+ } else {
834+ //DMA2 settings for OC4 for left
835+ DMACONSET=0x8000;
836+ DCH2CON=0x00000012; // CHBUSY=0, CHCHNS=0, CHEN=0, CHAED=0, CHCHN=0, CHAEN=1, CHEDET=0, CHPRI=b10
837+ DCH2ECON=0x1310; // CHAIRQ=0, CHSIRQ=19, CFORCE=0, CABRT=0, PATEN=0, SIRQEN=1, AIRQEN=0
838+ // CHSIRQ=19: Timer4 interrupt
839+ DCH2SSA=((unsigned int)&(wavtable[0]))&0x1fffffff;
840+ DCH2DSA=0x1F803620; // OC4RS
841+ DCH2SSIZ=524;
842+ DCH2DSIZ=1;
843+ DCH2CSIZ=1;
844+ DCH2INTCLR=0x00FF00FF;
845+ DCH2CONSET=0x00000080;
846+
847+ //DMA1 settings for OC3 for rifht
848+ DMACONSET=0x8000;
849+ DCH1CON=0x00000012; // CHBUSY=0, CHCHNS=0, CHEN=0, CHAED=0, CHCHN=0, CHAEN=1, CHEDET=0, CHPRI=b10
850+ DCH1ECON=0x1310; // CHAIRQ=0, CHSIRQ=19, CFORCE=0, CABRT=0, PATEN=0, SIRQEN=1, AIRQEN=0
851+ // CHSIRQ=19: Timer4 interrupt
852+ DCH1SSA=((unsigned int)&(wavtable[0]))&0x1fffffff;
853+ DCH1DSA=0x1F803420; // OC3RS
854+ DCH1SSIZ=524;
855+ DCH1DSIZ=1;
856+ DCH1CSIZ=1;
857+ DCH1INTCLR=0x00FF00FF;
858+ DCH1CONSET=0x00000080;
859+ }
860+
861+}
862+
863+void play_wave(char* filename, int start){
864+ // First of all, stop music.
865+ stop_music();
866+ // Exit function if null filename
867+ if (filename[0]==0x00) {
868+ OC3RS=OC4RS=0x80;
869+ return;
870+ }
871+ // Alocate 524*2 byte buffer if not assigned
872+ if (g_var_size[ALLOC_WAVE_BLOCK]==0) {
873+ wavtable=(char*)alloc_memory(524*2/4,ALLOC_WAVE_BLOCK);
874+ }
875+ // Open file
876+ if (g_fhandle) FSfclose(g_fhandle);
877+ g_fhandle=openWave(filename);
878+ // Support defined start position here to skip file pointer here.
879+ if (wave_stereo) start=start<<1;
880+ FSfseek(g_fhandle, start, SEEK_CUR);
881+ // Read first 262/524 words.
882+ if (wave_sector_size != FSfread((void*)&wavtable[0],1,wave_sector_size,g_fhandle)) err_file();
883+ // Initialize DMA
884+ init_wave_dma();
885+ g_sound_mode=SOUND_MODE_WAVE;
886+ // Enable intterupt
887+ IFS0bits.CS0IF=0;
888+ IEC0bits.CS0IE=1;
889+}
890+
891+void stop_music(){
892+ // Set NONE sound mode
893+ g_sound_mode=SOUND_MODE_NONE;
894+ // Stop DMA1 and DMA2
895+ DCH1CONCLR=0x00000080;
896+ DCH2CONCLR=0x00000080;
897+ // Close WAVE file if open
898+ if (g_fhandle) {
899+ FSfclose(g_fhandle);
900+ g_fhandle=0;
901+ }
902+}
--- mips/trunk/megalopa/envspecific.c (nonexistent)
+++ mips/trunk/megalopa/envspecific.c (revision 268)
@@ -0,0 +1,312 @@
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 "lib_video_megalopa.h"
12+#include "ps2keyboard.h"
13+#include "io.h"
14+
15+/*
16+ int readbuttons();
17+ Read the tact switches.
18+ For Zoea, disable PS/2 keyboard and enable tact switches, then read.
19+*/
20+
21+int readbuttons(){
22+ return KEYPORT;
23+}
24+
25+/*
26+ void pre_run(void);
27+ void post_run(void);
28+ Called before after execution of BASIC code.
29+*/
30+
31+void pre_run(void){
32+ // Reset PWM
33+ lib_pwm(0,0,0);
34+}
35+void post_run(void){
36+ if (graphmode==GMODE_ZOEAGRPH) {
37+ // Stop graph mode when using Zoea compatible one.
38+ usegraphic(0);
39+ g_use_graphic=0;
40+ }
41+}
42+
43+
44+
45+/*
46+ init_env();
47+ Initialize envionment.
48+*/
49+
50+void init_env(void){
51+ // Reset PWM
52+ lib_pwm(0,0,0);
53+}
54+
55+/*
56+ void scroll(int x, int y);
57+ Scroll
58+*/
59+
60+void scroll(int x,int y){
61+ int i,j;
62+ int vector=y*twidth+x;
63+ if (vector<0) {
64+ // Copy data from upper address to lower address
65+ for(i=0-vector;i<twidth*WIDTH_Y;i++){
66+ TVRAM[i+vector]=TVRAM[i];
67+ TVRAM[twidth*WIDTH_Y+i+vector]=TVRAM[twidth*WIDTH_Y+i];
68+ }
69+ } else if (0<vector) {
70+ // Copy data from lower address to upper address
71+ for(i=twidth*WIDTH_Y-vector-1;0<=i;i--){
72+ TVRAM[i+vector]=TVRAM[i];
73+ TVRAM[twidth*WIDTH_Y+i+vector]=TVRAM[twidth*WIDTH_Y+i];
74+ }
75+ } else {
76+ return;
77+ }
78+ if (x<0) {
79+ // Fill blanc at right
80+ for(i=x;i<0;i++){
81+ for(j=twidth+i;j<twidth*WIDTH_Y;j+=twidth){
82+ TVRAM[j]=0x00;
83+ TVRAM[twidth*WIDTH_Y+j]=cursorcolor;
84+ }
85+ }
86+ } else if (0<x) {
87+ // Fill blanc at left
88+ for(i=0;i<x;i++){
89+ for(j=i;j<twidth*WIDTH_Y;j+=twidth){
90+ TVRAM[j]=0x00;
91+ TVRAM[twidth*WIDTH_Y+j]=cursorcolor;
92+ }
93+ }
94+ }
95+ if (y<0) {
96+ // Fill blanc at bottom
97+ for(i=twidth*(WIDTH_Y+y);i<twidth*WIDTH_Y;i++){
98+ TVRAM[i]=0x00;
99+ TVRAM[twidth*WIDTH_Y+i]=cursorcolor;
100+ }
101+ } else if (0<y) {
102+ // Fill blanc at top
103+ for(i=0;i<twidth*y;i++){
104+ TVRAM[i]=0x00;
105+ TVRAM[twidth*WIDTH_Y+i]=cursorcolor;
106+ }
107+ }
108+}
109+
110+void allocate_graphic_area(int mode){
111+ static int prevmode=-1;
112+ if (g_graphic_area) {
113+ if (mode==prevmode) {
114+ // Do nothing
115+ return;
116+ } else {
117+ // Clear previous area here
118+ free_temp_str((char*)g_graphic_area);
119+ g_graphic_area=0;
120+ }
121+ }
122+ switch (mode) {
123+ case 0:
124+ g_graphic_area=alloc_memory(X_RESZ*Y_RESZ/2/4,ALLOC_GRAPHIC_BLOCK);
125+ break;
126+ case 1:
127+ g_graphic_area=alloc_memory(X_RES*Y_RES/4,ALLOC_GRAPHIC_BLOCK);
128+ break;
129+ case 2:
130+ g_graphic_area=alloc_memory(X_RESW*Y_RES/4,ALLOC_GRAPHIC_BLOCK);
131+ break;
132+ default:
133+ err_invalid_param();
134+ }
135+ // Store current graphic mode
136+ prevmode=mode;
137+}
138+
139+void start_graphic(int mode){
140+ if (!g_graphic_area) return;
141+ switch (mode) {
142+ case 0:
143+ set_videomode(VMODE_ZOEAGRPH,(unsigned char *)g_graphic_area);
144+ break;
145+ case 1:
146+ set_videomode(VMODE_STDGRPH,(unsigned char *)g_graphic_area);
147+ break;
148+ case 2:
149+ set_videomode(VMODE_WIDEGRPH,(unsigned char *)g_graphic_area);
150+ break;
151+ default:
152+ err_invalid_param();
153+ }
154+}
155+
156+void usegraphic(int mode){
157+ if (mode<0 || 11<mode) err_invalid_param();
158+ switch(mode & 3){
159+ // Modes; 0: stop GRAPHIC, 1: use GRAPHIC, 2: reset GRAPHIC and use it, 3: allocate GRAPHIC area but not use it
160+ case 0:
161+ if (g_use_graphic){
162+ // Stop GRAPHIC if used
163+ set_videomode(textmode,0);
164+ g_use_graphic=0;
165+ } else {
166+ // Prepare GRAPHIC area if not used and not allcated.
167+ allocate_graphic_area(mode>>2);
168+ }
169+ break;
170+ case 2:
171+ // Reset GRAPHIC and use it
172+ if (g_graphic_area) {
173+ g_clearscreen();
174+ init_palette();
175+ }
176+ // Continue to case 1:
177+ case 1:
178+ case 3:
179+ default:
180+ // Use GRAPHIC
181+ allocate_graphic_area(mode>>2);
182+ // Start showing GRAPHIC with mode 1, but not with mode 3
183+ if ((mode & 3) !=3 && !g_use_graphic){
184+ // Change to graphic mode.
185+ start_graphic(mode>>2);
186+ g_use_graphic=1;
187+ }
188+ break;
189+ }
190+}
191+
192+int lib_system(int a0, int a1 ,int v0, int a3, int g_gcolor, int g_prev_x, int g_prev_y){
193+ switch((enum extra)(a3 & EXTRA_MASK)){
194+ case EXTRA_SYSTEM:
195+ // SYSTEM statement/function (see below)
196+ break;
197+ case EXTRA_OUT:
198+ lib_out(g_libparams[1],v0);
199+ return v0;
200+ case EXTRA_OUT8H:
201+ lib_out8h(v0);
202+ return v0;
203+ case EXTRA_OUT8L:
204+ lib_out8l(v0);
205+ return v0;
206+ case EXTRA_OUT16:
207+ lib_out16(v0);
208+ return v0;
209+ case EXTRA_IN:
210+ return lib_in(v0);
211+ case EXTRA_IN8H:
212+ return lib_in8h();
213+ case EXTRA_IN8L:
214+ return lib_in8l();
215+ case EXTRA_IN16:
216+ return lib_in16();
217+ case EXTRA_ANALOG:
218+ return lib_analog(v0);
219+ case EXTRA_PWM:
220+ lib_pwm(g_libparams[1],g_libparams[2],v0);
221+ return v0;
222+ case EXTRA_SERIAL:
223+ lib_serial(g_libparams[1],g_libparams[2],v0);
224+ return v0;
225+ case EXTRA_SERIALOUT:
226+ lib_serialout(v0);
227+ return v0;
228+ case EXTRA_SERIALIN:
229+ return lib_serialin(v0);
230+ case EXTRA_SPI:
231+ case EXTRA_SPIOUT:
232+ case EXTRA_SPIIN:
233+ // TODO: Implement IO functions
234+ return v0;
235+ default:
236+ err_unknown();
237+ return v0;
238+ }
239+ switch(a0){
240+ // Version info
241+ case 0: return (int)SYSVER1;
242+ case 1: return (int)SYSVER2;
243+ case 2: return (int)BASVER;
244+ case 3: return (int)FILENAME_FLASH_ADDRESS;
245+ // Display info
246+ case 20: return twidth;
247+ case 21: return twidthy;
248+ case 22: return gwidth;
249+ case 23: return gwidthy;
250+ case 24: return cursorcolor;
251+ case 25: return g_gcolor;
252+ case 26: return ((int)(cursor-TVRAM))%twidth;
253+ case 27: return ((int)(cursor-TVRAM))/twidth;
254+ case 28: return g_prev_x;
255+ case 29: return g_prev_y;
256+ // Keyboard info
257+ case 40: return (int)inPS2MODE();
258+ case 41: return (int)vkey;
259+ case 42: return (int)lockkey;
260+ case 43: return (int)keytype;
261+ // Pointers to gloval variables
262+ case 100: return (int)&g_var_mem[0];
263+ case 101: return (int)&g_rnd_seed;
264+ case 102: return (int)&TVRAM[0];
265+ case 103: return (int)&FontData[0];
266+ case 104: return (int)g_var_mem[ALLOC_PCG_BLOCK];
267+ case 105: return (int)g_var_mem[ALLOC_GRAPHIC_BLOCK];
268+ // Change system settings
269+ case 200:
270+ // ON/OFF monitor
271+ if (v0) {
272+ start_composite();
273+ } else {
274+ stop_composite();
275+ }
276+ break;
277+ default:
278+ break;
279+ }
280+ return 0;
281+}
282+
283+void videowidth(int width){
284+ switch(width){
285+ case 30:
286+ set_videomode(VMODE_T30,0);
287+ break;
288+ case 36:
289+ set_videomode(VMODE_STDTEXT,0);
290+ break;
291+ case 40:
292+ set_videomode(VMODE_T40,0);
293+ break;
294+ case 48:
295+ set_videomode(VMODE_WIDETEXT,0);
296+ break;
297+ case 64:
298+ set_videomode(VMODE_WIDETEXT6dot,0);
299+ break;
300+ case 80:
301+ set_videomode(VMODE_MONOTEXT,0);
302+ break;
303+ default:
304+ // Do nothing
305+ return;
306+ }
307+ g_use_graphic=0;
308+}
309+
310+void set_graphmode(unsigned char m){
311+ if (m==0) set_videomode(VMODE_T30,0);
312+}
--- mips/trunk/megalopa/compiler.h (nonexistent)
+++ mips/trunk/megalopa/compiler.h (revision 268)
@@ -0,0 +1,376 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by Katsumi.
4+ http://hp.vector.co.jp/authors/VA016157/
5+ kmorimatsu@users.sourceforge.jp
6+*/
7+
8+// Include envilonment specific configurations
9+#include "envspecific.h"
10+
11+/* Definitions */
12+// Number of variables (including temporary ones)
13+#define ALLOC_VAR_NUM 36
14+// Block # dedicated for PCG
15+#define ALLOC_PCG_BLOCK 36
16+// Block # dedicated for GRAPHIC
17+#define ALLOC_GRAPHIC_BLOCK 37
18+// Block # dedicated for PLAYWAVE
19+#define ALLOC_WAVE_BLOCK 38
20+// Start # for long name variables
21+#define ALLOC_LNV_BLOCK 39
22+// Number of long name variables
23+#define ALLOC_LNV_NUM 190
24+// Start # of permanent blocks
25+#define ALLOC_PERM_BLOCK 229
26+// Number of blocks that can be assigned for memory allocation (including all above)
27+#define ALLOC_BLOCK_NUM 239
28+
29+// Persistent RAM bytes used for object, heap and exception data
30+#ifndef PERSISTENT_RAM_SIZE
31+ // This must be defined in envspecific.h
32+ #define PERSISTENT_RAM_SIZE (1024*53)
33+#endif
34+// Exception data area bytes
35+#define EXCEPTION_DATA_SIZE (64)
36+// RAM size used for object and heap
37+#define RAMSIZE (PERSISTENT_RAM_SIZE-EXCEPTION_DATA_SIZE)
38+
39+/* Enums */
40+enum variable{
41+ VAR_INTEGER,
42+ VAR_FLOAT,
43+ VAR_STRING
44+};
45+
46+#define OP_MASK 0x001F
47+enum operator{
48+ OP_VOID=0,
49+ OP_OR =1,
50+ OP_AND =2,
51+ OP_XOR =3,
52+ OP_EQ =4,
53+ OP_NEQ =5,
54+ OP_LT =6,
55+ OP_LTE =7,
56+ OP_MT =8,
57+ OP_MTE =9,
58+ OP_SHL =10,
59+ OP_SHR =11,
60+ OP_ADD =12,
61+ OP_SUB =13,
62+ OP_MUL =14,
63+ OP_DIV =15,
64+ OP_REM =16
65+};
66+
67+#define LIB_MASK 0xFE00
68+#define LIB_STEP 0x0200
69+enum libs{
70+ LIB_SOUND =LIB_STEP*0,
71+ LIB_MUSICFUNC =LIB_STEP*1,
72+ LIB_MUSIC =LIB_STEP*2,
73+ LIB_SETDRAWCOUNT =LIB_STEP*3,
74+ LIB_DRAWCOUNT =LIB_STEP*4,
75+ LIB_PALETTE =LIB_STEP*5,
76+ LIB_GPALETTE =LIB_STEP*6,
77+ LIB_BGCOLOR =LIB_STEP*7,
78+ LIB_CURSOR =LIB_STEP*8,
79+ LIB_CLS =LIB_STEP*9,
80+ LIB_GCLS =LIB_STEP*10,
81+ LIB_COLOR =LIB_STEP*11,
82+ LIB_GCOLOR =LIB_STEP*12,
83+ LIB_KEYS =LIB_STEP*13,
84+ LIB_RESTORE =LIB_STEP*14,
85+ LIB_RESTORE2 =LIB_STEP*15,
86+ LIB_READ =LIB_STEP*16,
87+ LIB_MIDSTR =LIB_STEP*17,
88+ LIB_CLEAR =LIB_STEP*18,
89+ LIB_DIV0 =LIB_STEP*19,
90+ LIB_LETSTR =LIB_STEP*20,
91+ LIB_STRNCMP =LIB_STEP*21,
92+ LIB_RND =LIB_STEP*22,
93+ LIB_DEC =LIB_STEP*23,
94+ LIB_HEX =LIB_STEP*24,
95+ LIB_CHR =LIB_STEP*25,
96+ LIB_CONNECT_STRING =LIB_STEP*26,
97+ LIB_STRING =LIB_STEP*27,
98+ LIB_PRINTSTR =LIB_STEP*28,
99+ LIB_LABEL =LIB_STEP*29,
100+ LIB_DIM =LIB_STEP*30,
101+ LIB_VAL =LIB_STEP*31,
102+ LIB_INPUT =LIB_STEP*32,
103+ LIB_INKEY =LIB_STEP*33,
104+ LIB_USEPCG =LIB_STEP*34,
105+ LIB_PCG =LIB_STEP*35,
106+ LIB_SCROLL =LIB_STEP*36,
107+ LIB_WAIT =LIB_STEP*37,
108+ LIB_VAR_PUSH =LIB_STEP*38,
109+ LIB_VAR_POP =LIB_STEP*39,
110+ LIB_SYSTEM =LIB_STEP*40,
111+ LIB_SPRINTF =LIB_STEP*41,
112+ LIB_FLOAT =LIB_STEP*42,
113+ LIB_FLOATFUNCS =LIB_STEP*43,
114+ LIB_CREAD =LIB_STEP*44,
115+ LIB_USEGRAPHIC =LIB_STEP*45,
116+ LIB_GRAPHIC =LIB_STEP*46,
117+ LIB_WIDTH =LIB_STEP*47,
118+ LIB_FILE =LIB_STEP*48,
119+ LIB_PLAYWAVE =LIB_STEP*49,
120+ LIB_PLAYWAVEFUNC =LIB_STEP*50,
121+ LIB_DEBUG =LIB_STEP*127,
122+};
123+
124+// Note: OP_XXXX and FUNC_XXXX cannot be used simultaneously
125+#define FUNC_MASK 0x003F
126+#define FUNC_STEP 0x0001
127+enum functions{
128+ FUNC_FLOAT =FUNC_STEP*0,
129+ FUNC_INT =FUNC_STEP*1,
130+ FUNC_VALSHARP =FUNC_STEP*2,
131+ FUNC_SIN =FUNC_STEP*3,
132+ FUNC_COS =FUNC_STEP*4,
133+ FUNC_TAN =FUNC_STEP*5,
134+ FUNC_ASIN =FUNC_STEP*6,
135+ FUNC_ACOS =FUNC_STEP*7,
136+ FUNC_ATAN =FUNC_STEP*8,
137+ FUNC_ATAN2 =FUNC_STEP*9,
138+ FUNC_SINH =FUNC_STEP*10,
139+ FUNC_COSH =FUNC_STEP*11,
140+ FUNC_TANH =FUNC_STEP*12,
141+ FUNC_EXP =FUNC_STEP*13,
142+ FUNC_LOG =FUNC_STEP*14,
143+ FUNC_LOG10 =FUNC_STEP*15,
144+ FUNC_POW =FUNC_STEP*16,
145+ FUNC_SQRT =FUNC_STEP*17,
146+ FUNC_CEIL =FUNC_STEP*18,
147+ FUNC_FLOOR =FUNC_STEP*19,
148+ FUNC_FABS =FUNC_STEP*20,
149+ FUNC_MODF =FUNC_STEP*21,
150+ FUNC_FMOD =FUNC_STEP*22,
151+ FUNC_PSET =FUNC_STEP*23,
152+ FUNC_LINE =FUNC_STEP*24,
153+ FUNC_BOXFILL =FUNC_STEP*25,
154+ FUNC_CIRCLE =FUNC_STEP*26,
155+ FUNC_CIRCLEFILL =FUNC_STEP*27,
156+ FUNC_GPRINT =FUNC_STEP*28,
157+ FUNC_PUTBMP =FUNC_STEP*29,
158+ FUNC_PUTBMP2 =FUNC_STEP*30,
159+ FUNC_GCOLOR =FUNC_STEP*31,
160+ FUNC_POINT =FUNC_STEP*32,
161+ FUNC_FOPEN =FUNC_STEP*33,
162+ FUNC_FOPENST =FUNC_STEP*34,
163+ FUNC_FILE =FUNC_STEP*35,
164+ FUNC_FCLOSE =FUNC_STEP*36,
165+ FUNC_FINPUT =FUNC_STEP*37,
166+ FUNC_FPRINTSTR =FUNC_STEP*38,
167+ FUNC_FGET =FUNC_STEP*39,
168+ FUNC_FPUT =FUNC_STEP*40,
169+ FUNC_FSEEK =FUNC_STEP*41,
170+ FUNC_FTELL =FUNC_STEP*42,
171+ FUNC_FLEN =FUNC_STEP*43,
172+ FUNC_FSTRING =FUNC_STEP*44,
173+ FUNC_FGETC =FUNC_STEP*45,
174+ FUNC_FPUTC =FUNC_STEP*46,
175+ FUNC_FREMOVE =FUNC_STEP*47,
176+ FUNC_FEOF =FUNC_STEP*48,
177+ FUNC_FINIT =FUNC_STEP*49,
178+ // MAX 63
179+};
180+
181+/* Global vars (see globalvers.c) */
182+extern int g_intconst;
183+extern char g_valueisconst;
184+extern unsigned int g_rnd_seed;
185+extern unsigned int g_label;
186+extern int g_sdepth;
187+extern int g_maxsdepth;
188+extern enum variable g_lastvar;
189+extern char* g_source;
190+extern int g_srcpos;
191+extern int g_line;
192+extern int g_fileline;
193+extern int* g_object;
194+extern int g_objpos;
195+extern int* g_objmax;
196+extern const char* g_err_str[];
197+extern const unsigned char g_priority[];
198+extern enum operator g_last_op;
199+extern int g_end_addr;
200+extern int g_gp;
201+extern int g_s6;
202+extern char RAM[RAMSIZE];
203+extern unsigned int g_ex_data[EXCEPTION_DATA_SIZE/4];
204+extern int g_var_mem[ALLOC_BLOCK_NUM];
205+extern unsigned short g_var_pointer[ALLOC_BLOCK_NUM];
206+extern unsigned short g_var_size[ALLOC_BLOCK_NUM];
207+extern char g_temp_area_used;
208+extern int* g_heap_mem;
209+extern int g_max_mem;
210+extern char g_disable_break;
211+extern unsigned char* g_pcg_font;
212+extern char g_use_graphic;
213+extern unsigned short* g_graphic_area;
214+extern int* g_libparams;
215+extern int g_long_name_var_num;
216+extern int g_temp;
217+
218+/* Prototypes */
219+int get_gp(void);
220+int get_fp(void);
221+void start_program(void* addr, void* memory);
222+void shift_obj(int* src, int* dst, int len);
223+char* compile_line(void);
224+int nextCodeIs(char* str);
225+int endOfStatement();
226+
227+char* init_file(char* buff,char* appname);
228+void close_file();
229+void read_file(int blocklen);
230+char* compile_file();
231+
232+void err_break(void);
233+void err_music(char* str);
234+void err_data_not_found(void);
235+void err_str_complex(void);
236+void err_label_not_found(void);
237+void err_no_mem(void);
238+void err_div_zero(void);
239+void err_unkonwn(void);
240+void err_unexp_next(void);
241+void err_no_block(void);
242+void err_invalid_param(void);
243+void err_file(void);
244+void err_wave(void);
245+char* resolve_label(int s6);
246+
247+void set_sound(unsigned long* data, int flagsLR);
248+int musicRemaining(int flagsLR);
249+int waveRemaining(int mode);
250+void set_music(char* str, int flagsLR);
251+void stop_music(void);
252+void init_music(void);
253+void play_wave(char* filename, int start);
254+
255+char* statement(void);
256+char* gosub_statement();
257+char* graphic_statement(enum functions func);
258+char* fopen_statement_main(enum functions func);
259+char* fget_statement();
260+char* fput_statement();
261+char* fputc_statement();
262+char* fremove_statement();
263+
264+char* function(void);
265+char* str_function(void);
266+char* float_function(void);
267+
268+void call_library(void);
269+void reset_dataread();
270+
271+void free_temp_str(char* str);
272+void* alloc_memory(int size, int var_num);
273+void* calloc_memory(int size, int var_num);
274+void move_to_perm_block(int var_num);
275+void move_from_perm_block(int var_num);
276+int get_permanent_var_num(void);
277+
278+char* link(void);
279+char* get_label(void);
280+void* search_label(unsigned int label);
281+
282+char* get_string();
283+char* simple_string(void);
284+
285+char* get_operator(void);
286+char* get_floatOperator(void);
287+char* calculation(enum operator op);
288+char* calculation_float(enum operator op);
289+int lib_float(int ia0,int iv0, enum operator a1);
290+
291+int lib_file(enum functions func, int a0, int a1, int v0);
292+
293+char* get_dim_value(int i);
294+char* get_simple_value(void);
295+char* get_value();
296+char* get_floatOrValue();
297+char* get_stringFloatOrValue();
298+
299+void blue_screen(void);
300+
301+char* get_float();
302+
303+void cmpdata_init();
304+char* cmpdata_insert(unsigned char type, short data16, int* data, unsigned char num);
305+void cmpdata_reset();
306+int* cmpdata_find(unsigned char type);
307+int* cmpdata_findfirst(unsigned char type);
308+
309+int check_var_name();
310+int get_var_number();
311+int search_var_name(int nameint);
312+char* register_var_name(int nameint);
313+
314+
315+/* Error messages */
316+#define ERR_SYNTAX (char*)(g_err_str[0])
317+#define ERR_NE_BINARY (char*)(g_err_str[1])
318+#define ERR_NE_MEMORY (char*)(g_err_str[2])
319+#define ERR_DIV_0 (char*)(g_err_str[3])
320+#define ERR_NY_I (char*)(g_err_str[4])
321+#define ERR_LABEL_NF (char*)(g_err_str[5])
322+#define ERR_LABEL_LONG (char*)(g_err_str[6])
323+#define ERR_STR_COMPLEX (char*)(g_err_str[7])
324+#define ERR_DATA_NF (char*)(g_err_str[8])
325+#define ERR_UNKNOWN (char*)(g_err_str[9])
326+#define ERR_MUSIC (char*)(g_err_str[10])
327+#define ERR_MULTIPLE_LABEL (char*)(g_err_str[11])
328+#define ERR_BREAK (char*)(g_err_str[12])
329+#define ERR_UNEXP_NEXT (char*)(g_err_str[13])
330+#define ERR_NO_BLOCK (char*)(g_err_str[14])
331+#define ERR_GOSUB_ASH (char*)(g_err_str[15])
332+#define ERR_INVALID_BREAK (char*)(g_err_str[16])
333+#define ERR_INVALID_ELSEIF (char*)(g_err_str[17])
334+#define ERR_INVALID_PARAM (char*)(g_err_str[18])
335+#define ERR_FILE (char*)(g_err_str[19])
336+#define ERR_INVALID_VAR_NAME (char*)(g_err_str[20])
337+#define ERR_WAVE (char*)(g_err_str[21])
338+
339+/* comple data type numbers */
340+#define CMPDATA_RESERVED 0
341+#define CMPDATA_USEVAR 1
342+
343+/* Macros */
344+
345+// Skip blanc(s) in source code
346+#define next_position() while(g_source[g_srcpos]==' ') {g_srcpos++;}
347+
348+// Check if object area is not full.
349+#define check_obj_space(x) if (g_objmax<g_object+g_objpos+(x)) return ERR_NE_BINARY
350+
351+// Returns priority of operator
352+#define priority(x) (int)g_priority[(int)(x)]
353+
354+// Insert code for calling library
355+//02E0F809 jalr ra,s7
356+//24070000 addiu a3,zero,0000
357+#define call_lib_code(x) \
358+ check_obj_space(2);\
359+ g_object[g_objpos++]=0x02E0F809;\
360+ g_object[g_objpos++]=0x24070000|((x)&0x0000FFFF)
361+
362+// Division macro for unsigned long
363+// Valid for 31 bits for all cases and 32 bits for some cases
364+#define div32(x,y,z) ((((unsigned long long)((unsigned long)(x)))*((unsigned long long)((unsigned long)(y))))>>(z))
365+
366+// Divide by 9 (valid for 32 bits)
367+#define div9_32(x) div32(x,0xe38e38e4,35)
368+#define rem9_32(x) ((x)-9*div9_32(x))
369+
370+// Divide by 10 (valid for 32 bits)
371+#define div10_32(x) div32(x,0xcccccccd,35)
372+#define rem10_32(x) ((x)-10*div10_32(x))
373+
374+// Divide by 36 (valid for 32 bits)
375+#define div36_32(x) div32(x,0xe38e38e4,37)
376+#define rem36_32(x) (x-36*div36_32(x))
--- mips/trunk/megalopa/function.c (nonexistent)
+++ mips/trunk/megalopa/function.c (revision 268)
@@ -0,0 +1,588 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by Katsumi.
4+ http://hp.vector.co.jp/authors/VA016157/
5+ kmorimatsu@users.sourceforge.jp
6+*/
7+
8+#include "compiler.h"
9+#include "api.h"
10+
11+char* music_function(){
12+ char* err;
13+ next_position();
14+ if (g_source[g_srcpos]==')') {
15+ check_obj_space(1);
16+ g_object[g_objpos++]=0x34020003; //ori v0,zero,0x03
17+ } else {
18+ err=get_value();
19+ if (err) return err;
20+ }
21+ call_lib_code(LIB_MUSICFUNC);
22+ return 0;
23+}
24+
25+char* read_function(){
26+ call_lib_code(LIB_READ);
27+ return 0;
28+}
29+
30+char* cread_function(){
31+ call_lib_code(LIB_CREAD);
32+ return 0;
33+}
34+
35+char* gosub_function(){
36+ // Check if garbage collection has been done.
37+ // This check is required because the used temporary area would be changed
38+ // in sub routine.
39+ if (g_temp_area_used) return ERR_GOSUB_ASH;
40+ return gosub_statement();
41+}
42+char* strncmp_function(){
43+ char* err;
44+ err=get_string();
45+ if (err) return err;
46+ check_obj_space(2);
47+ g_object[g_objpos++]=0x27BDFFF8; // addiu sp,sp,-8
48+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
49+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
50+ g_srcpos++;
51+ err=get_string();
52+ if (err) return err;
53+ check_obj_space(1);
54+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
55+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
56+ g_srcpos++;
57+ err=get_value();
58+ if (err) return err;
59+ call_lib_code(LIB_STRNCMP);
60+ check_obj_space(1);
61+ g_object[g_objpos++]=0x27BD0008; // addiu sp,sp,8
62+ return 0;
63+}
64+char* len_function(){
65+ char* err;
66+ err=get_string();
67+ if (err) return err;
68+ check_obj_space(5);
69+ g_object[g_objpos++]=0x2443FFFF; // addiu v1,v0,-1
70+ // loop:
71+ g_object[g_objpos++]=0x80640001; // lb a0,1(v1)
72+ g_object[g_objpos++]=0x1480FFFE; // bne a0,zero,loop
73+ g_object[g_objpos++]=0x24630001; // addiu v1,v1,1
74+ g_object[g_objpos++]=0x00621023; // subu v0,v1,v0
75+ return 0;
76+}
77+
78+char* asc_function(){
79+ char* err;
80+ err=get_string();
81+ if (err) return err;
82+ check_obj_space(1);
83+ g_object[g_objpos++]=0x90420000; // lbu v0,0(v0)
84+ return 0;
85+}
86+
87+char* val_function(){
88+ char* err;
89+ err=get_string();
90+ if (err) return err;
91+ call_lib_code(LIB_VAL);
92+ return 0;
93+}
94+
95+char* peek_function(){
96+ char* err;
97+ err=get_value();
98+ if (err) return err;
99+ check_obj_space(1);
100+ g_object[g_objpos++]=0x90420000; // lbu v0,0(v0)
101+ return 0;
102+}
103+
104+char* sgn_function(){
105+ char* err;
106+ err=get_value();
107+ if (err) return err;
108+ check_obj_space(5);
109+ g_object[g_objpos++]=0x10400004; // beq v0,zero,end
110+ g_object[g_objpos++]=0x24030001; // addiu v1,zero,1
111+ g_object[g_objpos++]=0x1C400002; // bgtz v0,end
112+ g_object[g_objpos++]=0x00601021; // addu v0,v1,zero
113+ g_object[g_objpos++]=0x00031023; // subu v0,zero,v1
114+ // end:
115+ return 0;
116+}
117+
118+char* abs_function(){
119+ char* err;
120+ err=get_value();
121+ if (err) return err;
122+ check_obj_space(3);
123+ g_object[g_objpos++]=0x00021FC3; //sra v1,v0,0x1f
124+ g_object[g_objpos++]=0x00621026; //xor v0,v1,v0
125+ g_object[g_objpos++]=0x00431023; //subu v0,v0,v1
126+ return 0;
127+}
128+
129+char* not_function(){
130+ char* err;
131+ err=get_value();
132+ if (err) return err;
133+ check_obj_space(1);
134+ g_object[g_objpos++]=0x2C420001; //sltiu v0,v0,1
135+ return 0;
136+}
137+
138+char* rnd_function(){
139+ call_lib_code(LIB_RND);
140+ return 0;
141+}
142+
143+
144+char* chr_function(void){
145+ char* err;
146+ err=get_value();
147+ if (err) return err;
148+ call_lib_code(LIB_CHR);
149+ return 0;
150+}
151+char* hex_function(void){
152+ char* err;
153+ err=get_value();
154+ if (err) return err;
155+ if (g_source[g_srcpos]==',') {
156+ // Second argument found.
157+ // Get is as $a0.
158+ g_srcpos++;
159+ check_obj_space(2);
160+ g_object[g_objpos++]=0x27BDFFFC; //addiu sp,sp,-4
161+ g_object[g_objpos++]=0xAFA20004; //sw v0,4(sp)
162+ err=get_value();
163+ if (err) return err;
164+ check_obj_space(3);
165+ g_object[g_objpos++]=0x00022021; //a0,zero,v0
166+ g_object[g_objpos++]=0x8FA20004; //lw v0,4(sp)
167+ g_object[g_objpos++]=0x27BD0004; //addiu sp,sp,4
168+ } else {
169+ // Second argument not found.
170+ // Set $a0 to 0.
171+ check_obj_space(1);
172+ g_object[g_objpos++]=0x24040000; //addiu a0,zero,0
173+ }
174+ call_lib_code(LIB_HEX);
175+ return 0;
176+}
177+
178+char* dec_function(void){
179+ char* err;
180+ err=get_value();
181+ if (err) return err;
182+ call_lib_code(LIB_DEC);
183+ return 0;
184+}
185+
186+char* keys_function(void){
187+ char* err;
188+ next_position();
189+ if (g_source[g_srcpos]==')') {
190+ check_obj_space(1);
191+ g_object[g_objpos++]=0x3402003F; //ori v0,zero,0x3f
192+ } else {
193+ err=get_value();
194+ if (err) return err;
195+ }
196+ call_lib_code(LIB_KEYS);
197+ return 0;
198+}
199+
200+char* tvram_function(void){
201+ char* err;
202+ int i;
203+ next_position();
204+ if (g_source[g_srcpos]==')') {
205+ i=(int)(&TVRAM[0]);
206+ i-=g_gp;
207+ check_obj_space(1);
208+ g_object[g_objpos++]=0x27820000|(i&0x0000FFFF); // addiu v0,gp,xxxx
209+ } else {
210+ err=get_value();
211+ if (err) return err;
212+ i=(int)(&TVRAM[0]);
213+ i-=g_gp;
214+ check_obj_space(3);
215+ g_object[g_objpos++]=0x27830000|(i&0x0000FFFF); // addiu v1,gp,xxxx
216+ g_object[g_objpos++]=0x00621821; // addu v1,v1,v0
217+ g_object[g_objpos++]=0x90620000; // lbu v0,0(v1)
218+ }
219+ return 0;
220+}
221+
222+char* drawcount_function(void){
223+ call_lib_code(LIB_DRAWCOUNT);
224+ return 0;
225+}
226+
227+char* input_function(void){
228+ call_lib_code(LIB_INPUT);
229+ return 0;
230+}
231+
232+char* inkey_function(void){
233+ char* err;
234+ next_position();
235+ if (g_source[g_srcpos]==')') {
236+ check_obj_space(1);
237+ g_object[g_objpos++]=0x34020000; //ori v0,zero,0x00
238+ } else {
239+ err=get_value();
240+ if (err) return err;
241+ }
242+ call_lib_code(LIB_INKEY);
243+ return 0;
244+}
245+
246+char* args_function(void){
247+ char* err;
248+ int i;
249+ err=get_value();
250+ if (err) return err;
251+ i=g_object[g_objpos-1];
252+ if ((i>>16)==0x3402) {
253+ // Previous object is "ori v0,zero,xxxx".
254+ i&=0xffff;
255+ i=(i+1)<<2;
256+ g_object[g_objpos-1]=0x8EA20000|i; // lw v0,xx(s5)
257+ } else {
258+ check_obj_space(3);
259+ g_object[g_objpos++]=0x00021080; // sll v0,v0,0x2
260+ g_object[g_objpos++]=0x02A21021; // addu v0,s5,v0
261+ g_object[g_objpos++]=0x8C420004; // lw v0,4(v0)
262+ }
263+ return 0;
264+}
265+
266+char* system_function(void){
267+ char* err;
268+ err=get_value();
269+ if (err) return err;
270+ g_object[g_objpos++]=0x00402021; // addu a0,v0,zero
271+ call_lib_code(LIB_SYSTEM);
272+ return 0;
273+}
274+
275+char* sprintf_function(void){
276+ char* err;
277+ err=get_string();
278+ if (err) return err;
279+ next_position();
280+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
281+ g_srcpos++;
282+ check_obj_space(2);
283+ g_object[g_objpos++]=0x27BDFFFC; //addiu sp,sp,-4
284+ g_object[g_objpos++]=0xAFA20004; //sw v0,4(sp)
285+ err=get_float();
286+ if (err) return err;
287+ check_obj_space(3);
288+ g_object[g_objpos++]=0x00022021; //addu a0,zero,v0
289+ g_object[g_objpos++]=0x8FA20004; //lw v0,4(sp)
290+ g_object[g_objpos++]=0x27BD0004; //addiu sp,sp,4
291+ call_lib_code(LIB_SPRINTF);
292+ return 0;
293+}
294+
295+char* floatstr_function(void){
296+ char* err;
297+ err=get_float();
298+ if (err) return err;
299+ check_obj_space(2);
300+ g_object[g_objpos++]=0x00022021; //addu a0,zero,v0
301+ g_object[g_objpos++]=0x34020000; //ori v0,zero,0x0000
302+ call_lib_code(LIB_SPRINTF);
303+ return 0;
304+}
305+
306+char* floatsharp_function(void){
307+ char* err;
308+ err=get_value();
309+ if (err) return err;
310+ call_lib_code(LIB_FLOATFUNCS | FUNC_FLOAT);
311+ return 0;
312+}
313+
314+char* valsharp_function(void){
315+ char* err;
316+ err=get_string();
317+ if (err) return err;
318+ call_lib_code(LIB_FLOATFUNCS | FUNC_VALSHARP);
319+ return 0;
320+}
321+
322+char* int_function(void){
323+ char* err;
324+ err=get_float();
325+ if (err) return err;
326+ call_lib_code(LIB_FLOATFUNCS | FUNC_INT);
327+ return 0;
328+}
329+
330+char* fseek_function(){
331+ call_lib_code(LIB_FILE | FUNC_FTELL);
332+ return 0;
333+}
334+
335+char* flen_function(){
336+ call_lib_code(LIB_FILE | FUNC_FLEN);
337+ return 0;
338+}
339+
340+char* fgetc_function(){
341+ call_lib_code(LIB_FILE | FUNC_FGETC);
342+ return 0;
343+}
344+
345+char* finput_function(){
346+ char* err;
347+ next_position();
348+ if (g_source[g_srcpos]!=')') {
349+ err=get_value();
350+ if (err) return err;
351+ } else {
352+ // Parameter will be zero if not defined
353+ check_obj_space(1);
354+ g_object[g_objpos++]=0x34020000; // ori v0,zero,0
355+ }
356+ call_lib_code(LIB_FILE | FUNC_FINPUT);
357+ return 0;
358+}
359+
360+char* feof_function(){
361+ call_lib_code(LIB_FILE | FUNC_FEOF);
362+ return 0;
363+}
364+
365+char* playwave_function(){
366+ char* err;
367+ next_position();
368+ if (g_source[g_srcpos]!=')') {
369+ // Get param
370+ err=get_value();
371+ if (err) return err;
372+ } else {
373+ // If parameter is omitted, use 0.
374+ check_obj_space(1);
375+ g_object[g_objpos++]=0x24020000; // addiu v0,zero,0
376+ }
377+ call_lib_code(LIB_PLAYWAVEFUNC);
378+ return 0;
379+}
380+
381+char* float_constant(float val){
382+ volatile int i;
383+ ((float*)(&i))[0]=val;
384+ if (i&0xFFFF0000) {
385+ // 32 bit
386+ check_obj_space(2);
387+ g_object[g_objpos++]=0x3C020000|((i>>16)&0x0000FFFF); // lui v0,xxxx
388+ g_object[g_objpos++]=0x34420000|(i&0x0000FFFF); // ori v0,v0,xxxx
389+ } else {
390+ // 16 bit
391+ check_obj_space(1);
392+ g_object[g_objpos++]=0x34020000|(i&0x0000FFFF); // ori v0,zero,xxxx
393+ }
394+ return 0;
395+}
396+
397+char* float_1param_function(enum functions func){
398+ char* err;
399+ err=get_float();
400+ if (err) return err;
401+ call_lib_code(LIB_FLOATFUNCS | func);
402+ return 0;
403+}
404+
405+char* float_2param_function(enum functions func){
406+ char* err;
407+ err=get_float();
408+ if (err) return err;
409+ next_position();
410+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
411+ g_srcpos++;
412+ check_obj_space(2);
413+ g_object[g_objpos++]=0x27BDFFFC; //addiu sp,sp,-4
414+ g_object[g_objpos++]=0xAFA20004; //sw v0,4(sp)
415+ err=get_float();
416+ if (err) return err;
417+ check_obj_space(3);
418+ g_object[g_objpos++]=0x00022021; //addu a0,zero,v0
419+ g_object[g_objpos++]=0x8FA20004; //lw v0,4(sp)
420+ g_object[g_objpos++]=0x27BD0004; //addiu sp,sp,4
421+ call_lib_code(LIB_FLOATFUNCS | func);
422+ return 0;
423+}
424+
425+char* float_function(void){
426+ char* err;
427+ if (nextCodeIs("FLOAT#(")) {
428+ err=floatsharp_function();
429+ } else if (nextCodeIs("VAL#(")) {
430+ err=valsharp_function();
431+ } else if (nextCodeIs("SIN#(")) {
432+ err=float_1param_function(FUNC_SIN);
433+ } else if (nextCodeIs("COS#(")) {
434+ err=float_1param_function(FUNC_COS);
435+ } else if (nextCodeIs("TAN#(")) {
436+ err=float_1param_function(FUNC_TAN);
437+ } else if (nextCodeIs("ASIN#(")) {
438+ err=float_1param_function(FUNC_ASIN);
439+ } else if (nextCodeIs("ACOS#(")) {
440+ err=float_1param_function(FUNC_ACOS);
441+ } else if (nextCodeIs("ATAN#(")) {
442+ err=float_1param_function(FUNC_ATAN);
443+ } else if (nextCodeIs("ATAN2#(")) {
444+ err=float_2param_function(FUNC_ATAN2);
445+ } else if (nextCodeIs("SINH#(")) {
446+ err=float_1param_function(FUNC_SINH);
447+ } else if (nextCodeIs("COSH#(")) {
448+ err=float_1param_function(FUNC_COSH);
449+ } else if (nextCodeIs("TANH#(")) {
450+ err=float_1param_function(FUNC_TANH);
451+ } else if (nextCodeIs("EXP#(")) {
452+ err=float_1param_function(FUNC_EXP);
453+ } else if (nextCodeIs("LOG#(")) {
454+ err=float_1param_function(FUNC_LOG);
455+ } else if (nextCodeIs("LOG10#(")) {
456+ err=float_1param_function(FUNC_LOG10);
457+ } else if (nextCodeIs("POW#(")) {
458+ err=float_2param_function(FUNC_POW);
459+ } else if (nextCodeIs("SQRT#(")) {
460+ err=float_1param_function(FUNC_SQRT);
461+ } else if (nextCodeIs("CEIL#(")) {
462+ err=float_1param_function(FUNC_CEIL);
463+ } else if (nextCodeIs("FLOOR#(")) {
464+ err=float_1param_function(FUNC_FLOOR);
465+ } else if (nextCodeIs("FABS#(")) {
466+ err=float_1param_function(FUNC_FABS);
467+ } else if (nextCodeIs("MODF#(")) {
468+ err=float_1param_function(FUNC_MODF);
469+ } else if (nextCodeIs("FMOD#(")) {
470+ err=float_2param_function(FUNC_FMOD);
471+ } else if (nextCodeIs("GOSUB#(")) {
472+ err=gosub_function();
473+ } else if (nextCodeIs("ARGS#(")) {
474+ err=args_function();
475+ } else if (nextCodeIs("PI#")) {
476+ return float_constant(3.141593);
477+ } else {
478+ return ERR_SYNTAX;
479+ }
480+ if (err) return err;
481+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
482+ g_srcpos++;
483+ return 0;
484+}
485+
486+static const void* str_func_list[]={
487+ "CHR$(",chr_function,
488+ "HEX$(",hex_function,
489+ "DEC$(",dec_function,
490+ "INPUT$(",input_function,
491+ "GOSUB$(",gosub_function,
492+ "ARGS$(",args_function,
493+ "READ$(",read_function,
494+ "SPRINTF$(",sprintf_function,
495+ "FLOAT$(",floatstr_function,
496+ "SYSTEM$(",system_function,
497+ "FINPUT$(",finput_function,
498+ // Additional functions follow
499+ ADDITIONAL_STR_FUNCTIONS
500+};
501+
502+char* str_function(void){
503+ char* err;
504+ int i;
505+ char* (*f)();
506+ // Seek the function
507+ for (i=0;i<sizeof(str_func_list)/sizeof(str_func_list[0]);i+=2){
508+ if (nextCodeIs((char*)str_func_list[i])) break;
509+ }
510+ if (i<sizeof(str_func_list)/sizeof(str_func_list[0])) {
511+ // Function found. Call it.
512+ f=str_func_list[i+1];
513+ err=f();
514+ } else {
515+ return ERR_SYNTAX;
516+ }
517+ if (err) return err;
518+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
519+ g_srcpos++;
520+ return 0;
521+}
522+
523+// Aliases follow
524+
525+char* gcolor_function(){
526+ return graphic_statement(FUNC_GCOLOR);
527+}
528+
529+char* fopen_function(){
530+ return fopen_statement_main(FUNC_FOPEN);
531+}
532+
533+static const void* int_func_list[]={
534+ "NOT(",not_function,
535+ "DRAWCOUNT(",drawcount_function,
536+ "MUSIC(",music_function,
537+ "TVRAM(",tvram_function,
538+ "KEYS(",keys_function,
539+ "READ(",read_function,
540+ "CREAD(",cread_function,
541+ "GOSUB(",gosub_function,
542+ "STRNCMP(",strncmp_function,
543+ "PEEK(",peek_function,
544+ "LEN(",len_function,
545+ "ASC(",asc_function,
546+ "SGN(",sgn_function,
547+ "ABS(",abs_function,
548+ "RND(",rnd_function,
549+ "VAL(",val_function,
550+ "INKEY(",inkey_function,
551+ "ARGS(",args_function,
552+ "SYSTEM(",system_function,
553+ "INT(",int_function,
554+ "GCOLOR(",gcolor_function,
555+ "FOPEN(",fopen_function,
556+ "FSEEK(",fseek_function,
557+ "FLEN(",flen_function,
558+ "FGET(",fget_statement,
559+ "FPUT(",fput_statement,
560+ "FGETC(",fgetc_function,
561+ "FPUTC(",fputc_statement,
562+ "FREMOVE(",fremove_statement,
563+ "FEOF(",feof_function,
564+ "PLAYWAVE(",playwave_function,
565+ // Additional functions follow
566+ ADDITIONAL_INT_FUNCTIONS
567+};
568+
569+char* function(void){
570+ char* err;
571+ int i;
572+ char* (*f)();
573+ // Seek the function
574+ for (i=0;i<sizeof(int_func_list)/sizeof(int_func_list[0]);i+=2){
575+ if (nextCodeIs((char*)int_func_list[i])) break;
576+ }
577+ if (i<sizeof(int_func_list)/sizeof(int_func_list[0])) {
578+ // Function found. Call it.
579+ f=int_func_list[i+1];
580+ err=f();
581+ } else {
582+ return ERR_SYNTAX;
583+ }
584+ if (err) return err;
585+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
586+ g_srcpos++;
587+ return 0;
588+}
--- mips/trunk/megalopa/library.c (nonexistent)
+++ mips/trunk/megalopa/library.c (revision 268)
@@ -0,0 +1,1085 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by Katsumi.
4+ http://hp.vector.co.jp/authors/VA016157/
5+ kmorimatsu@users.sourceforge.jp
6+*/
7+
8+#include <xc.h>
9+#include "main.h"
10+#include "compiler.h"
11+#include "api.h"
12+#include "keyinput.h"
13+#include "stdlib.h"
14+#include "math.h"
15+
16+/*
17+ Local global variables used for graphic
18+ */
19+
20+static int g_gcolor=7;
21+static int g_prev_x=0;
22+static int g_prev_y=0;
23+
24+int lib_read(int mode, unsigned int label){
25+ unsigned int i,code,code2;
26+ static unsigned int pos=0;
27+ static unsigned int in_data=0;
28+ static unsigned char skip=0;
29+ if (label) {
30+ // RESTORE function
31+ switch(mode){
32+ case 0:
33+ // label is label data
34+ i=(int)search_label(label);
35+ if (!i) {
36+ err_data_not_found();
37+ return 0;
38+ }
39+ break;
40+ case 1:
41+ // label is pointer
42+ i=label;
43+ break;
44+ case 2:
45+ default:
46+ // Reset data/read
47+ pos=0;
48+ in_data=0;
49+ skip=0;
50+ return 0;
51+ }
52+ i-=(int)(&g_object[0]);
53+ pos=i/4;
54+ in_data=0;
55+ }
56+ // Get data
57+ if (in_data==0) {
58+ for(i=pos;i<g_objpos;i++){
59+ code=g_object[i];
60+ code2=g_object[i+1];
61+ if ((code&0xFFFF0000)!=0x04110000) continue;
62+ // "bgezal zero," assembly found.
63+ // Check if 0x00000020,0x00000021,0x00000022, or 0x00000023 follows
64+ if ((code2&0xfffffffc)!=0x00000020) {// add/addu/sub/subu zero,zero,zero
65+ // If not, skip following block (it's strig).
66+ i+=code&0x0000FFFF;
67+ continue;
68+ }
69+ // DATA region found.
70+ in_data=(code&0x0000FFFF)-1;
71+ pos=i+2;
72+ skip=code2&0x03;
73+ break;
74+ }
75+ if (g_objpos<=i) {
76+ err_data_not_found();
77+ return 0;
78+ }
79+ }
80+ if (label) {
81+ // RESTORE function. Return pointer.
82+ return ((int)&g_object[pos])+skip;
83+ } else {
84+ switch(mode){
85+ case 0:
86+ // READ() function
87+ in_data--;
88+ return g_object[pos++];
89+ case 1:
90+ default:
91+ // CREAD() function
92+ i=g_object[pos];
93+ i>>=skip*8;
94+ i&=0xff;
95+ if ((++skip)==4) {
96+ skip=0;
97+ in_data--;
98+ pos++;
99+ }
100+ return i;
101+ }
102+ }
103+}
104+
105+void reset_dataread(){
106+ lib_read(2,1);
107+}
108+
109+char* lib_midstr(int var_num, int pos, int len){
110+ int i;
111+ char* str;
112+ char* ret;
113+ if (0<=pos) {
114+ // String after "pos" position.
115+ str=(char*)(g_var_mem[var_num]+pos);
116+ } else {
117+ // String right "pos" characters.
118+ // Determine length
119+ str=(char*)g_var_mem[var_num];
120+ for(i=0;str[i];i++);
121+ if (0<=(i+pos)) {
122+ str=(char*)(g_var_mem[var_num]+i+pos);
123+ }
124+ }
125+ if (len<0) {
126+ // Length is not specified.
127+ // Return the string to the end.
128+ return str;
129+ }
130+ // Length is specified.
131+ // Construct temporary string containing specified number of characters.
132+ ret=alloc_memory((len+1+3)/4,-1);
133+ // Copy string.
134+ for(i=0;(ret[i]=str[i])&&(i<len);i++);
135+ ret[len]=0x00;
136+ return ret;
137+}
138+
139+void lib_clear(void){
140+ int i;
141+ // All variables (including temporary and permanent ones) will be integer 0
142+ for(i=0;i<ALLOC_BLOCK_NUM;i++){
143+ g_var_mem[i]=0;
144+ }
145+ // Clear memory allocation area
146+ for(i=0;i<ALLOC_BLOCK_NUM;i++){
147+ g_var_size[i]=0;
148+ }
149+ // Cancel PCG
150+ stopPCG();
151+ g_pcg_font=0;
152+ // Stop using graphic
153+ g_use_graphic=1; // Force set_graphmode(0) (see usegraphic() function)
154+ usegraphic(0);
155+}
156+
157+void lib_let_str(char* str, int var_num){
158+ int begin,end,size;
159+ // Save pointer
160+ g_var_mem[var_num]=(int)str;
161+ // Determine size
162+ for(size=0;str[size];size++);
163+ // Check if str is in heap area.
164+ begin=(int)str;
165+ end=(int)(&str[size]);
166+ if (begin<(int)(&g_heap_mem[0]) || (int)(&g_heap_mem[g_max_mem])<=end) {
167+ // String is not within allcated block
168+ return;
169+ }
170+ // Str is in heap area. Calculate values stored in heap data dimension
171+ begin-=(int)(&g_heap_mem[0]);
172+ begin>>=2;
173+ end-=(int)(&g_heap_mem[0]);
174+ end>>=2;
175+ size=end-begin+1;
176+ g_var_pointer[var_num]=begin;
177+ g_var_size[var_num]=size;
178+}
179+
180+int lib_rnd(){
181+ int y;
182+ y=g_rnd_seed;
183+ y = y ^ (y << 13);
184+ y = y ^ (y >> 17);
185+ y = y ^ (y << 5);
186+ g_rnd_seed=y;
187+ return y&0x7fff;
188+}
189+
190+char* lib_chr(int num){
191+ char* str;
192+ str=alloc_memory(1,-1);
193+ str[0]=num&0x000000FF;
194+ str[1]=0x00;
195+ return str;
196+}
197+
198+char* lib_dec(int num){
199+ char* str;
200+ int i,j,minus;
201+ char b[12];
202+ b[11]=0x00;
203+ if (num<0) {
204+ minus=1;
205+ num=0-num;
206+ } else {
207+ minus=0;
208+ }
209+ for (i=10;0<i;i--) {
210+ if (num==0 && i<10) break;
211+ b[i]='0'+rem10_32(num);
212+ num=div10_32(num);
213+ }
214+ if (minus) {
215+ b[i]='-';
216+ } else {
217+ i++;
218+ }
219+ str=alloc_memory(3,-1);
220+ for(j=0;str[j]=b[i++];j++);
221+ return str;
222+}
223+
224+char* lib_hex(int num, int width){
225+ char* str;
226+ int i,j,minus;
227+ char b[8];
228+ str=alloc_memory(3,-1);
229+ for(i=0;i<8;i++){
230+ b[i]="0123456789ABCDEF"[(num>>(i<<2))&0x0F];
231+ }
232+ // Width must be between 0 and 8;
233+ if (width<0||8<width) width=8;
234+ if (width==0) {
235+ // Width not asigned. Use minimum width.
236+ for(i=7;0<i;i--){
237+ if ('0'<b[i]) break;
238+ }
239+ } else {
240+ // Constant width
241+ i=width-1;
242+ }
243+ // Copy string to allocated block.
244+ for(j=0;0<=i;i--){
245+ str[j++]=b[i];
246+ }
247+ str[j]=0x00;
248+ return str;
249+}
250+
251+char* lib_connect_string(char* str1, char* str2){
252+ int i,j;
253+ char b;
254+ char* result;
255+ // Determine total length
256+ for(i=0;str1[i];i++);
257+ for(j=0;str2[j];j++);
258+ // Allocate a block for new string
259+ result=alloc_memory((i+j+1+3)/4,-1);
260+ // Create connected strings
261+ for(i=0;b=str1[i];i++) result[i]=b;
262+ for(j=0;b=str2[j];j++) result[i+j]=b;
263+ result[i+j]=0x00;
264+ free_temp_str(str1);
265+ free_temp_str(str2);
266+ return result;
267+}
268+
269+void lib_string(int mode){
270+ int i;
271+ switch(mode){
272+ case 0:
273+ // CR
274+ printchar('\n');
275+ return;
276+ case 1:
277+ // ,
278+ printcomma();
279+ return;
280+ default:
281+ return;
282+ }
283+}
284+
285+void* lib_label(unsigned int label){
286+ // This routine is used to jump to address dynamically determined
287+ // in the code; for example: "GOTO 100+I"
288+ unsigned int i,code,search;
289+ void* ret;
290+ if (label&0xFFFF0000) {
291+ // Label is not supported.
292+ // Line number must bs less than 65536.
293+ err_label_not_found();
294+ } else {
295+ // Line number
296+ ret=search_label(label);
297+ if (ret) return ret;
298+ // Line number not found.
299+ err_label_not_found();
300+ }
301+}
302+
303+int lib_keys(int mask){
304+ int keys;
305+ keys=readbuttons();
306+ keys=
307+ ((keys&KEYUP)? 0:1)|
308+ ((keys&KEYDOWN)? 0:2)|
309+ ((keys&KEYLEFT)? 0:4)|
310+ ((keys&KEYRIGHT)? 0:8)|
311+ ((keys&KEYSTART)? 0:16)|
312+ ((keys&KEYFIRE)? 0:32);
313+ return mask&keys;
314+}
315+
316+int lib_val(char* str){
317+ int i;
318+ int val=0;
319+ int sign=1;
320+ char b;
321+ // Skip blanc
322+ for(i=0;0<=str[i] && str[i]<0x21;i++);
323+ // Skip '+'
324+ if (str[i]=='+') i++;
325+ // Check '-'
326+ if (str[i]=='-') {
327+ sign=-1;
328+ i++;
329+ }
330+ // Check '0x' or '$'
331+ if (str[i]=='$' || str[i]=='0' && (str[i+1]=='x' || str[i+1]=='X')) {
332+ // Hexadecimal
333+ if (str[i++]=='0') i++;
334+ while(1) {
335+ b=str[i++];
336+ if ('0'<=b && b<='9') {
337+ val<<=4;
338+ val+=b-'0';
339+ } else if ('a'<=b && b<='f') {
340+ val<<=4;
341+ val+=b-'a'+10;
342+ } else if ('A'<=b && b<='F') {
343+ val<<=4;
344+ val+=b-'A'+10;
345+ } else {
346+ break;
347+ }
348+ }
349+ } else {
350+ // Decimal
351+ while(1) {
352+ b=str[i++];
353+ if ('0'<=b && b<='9') {
354+ val*=10;
355+ val+=b-'0';
356+ } else {
357+ break;
358+ }
359+ }
360+ }
361+ return val*sign;
362+}
363+
364+char* lib_input(){
365+ // Allocate memory for strings with 63 characters
366+ char *str=calloc_memory((63+1)/4,-1);
367+ // Enable PS/2 keyboard
368+ if (!inPS2MODE()) {
369+ ps2mode();
370+ ps2init();
371+ }
372+ // Clear key buffer
373+ do ps2readkey();
374+ while(vkey!=0);
375+ // Get string as a line
376+ lineinput(str,63);
377+ check_break();
378+ return str;
379+}
380+
381+unsigned char lib_inkey(int key){
382+ int i;
383+ // Enable PS/2 keyboard
384+ if (!inPS2MODE()) {
385+ ps2mode();
386+ ps2init();
387+ }
388+ if (key) {
389+ return ps2keystatus[key&0xff];
390+ } else {
391+ for(i=0;i<256;i++){
392+ if (ps2keystatus[i]) return i;
393+ }
394+ return 0;
395+ }
396+}
397+
398+void lib_usepcg(int mode){
399+ // Modes; 0: stop PCG, 1: use PCG, 2: reset PCG and use it
400+ switch(mode){
401+ case 0:
402+ // Stop PCG
403+ stopPCG();
404+ break;
405+ case 2:
406+ // Reset PCG and use it
407+ if (g_pcg_font) {
408+ free_temp_str(g_pcg_font);
409+ g_pcg_font=0;
410+ }
411+ // Continue to case 1:
412+ case 1:
413+ default:
414+ // Use PCG
415+ if (g_pcg_font) {
416+ startPCG(g_pcg_font,0);
417+ } else {
418+ g_pcg_font=alloc_memory(256*8/4,ALLOC_PCG_BLOCK);
419+ startPCG(g_pcg_font,1);
420+ }
421+ break;
422+ }
423+}
424+
425+void lib_pcg(unsigned int ascii,unsigned int fontdata1,unsigned int fontdata2){
426+ unsigned int* pcg;
427+ // If USEPCG has not yet executed, do now.
428+ if (!g_pcg_font) lib_usepcg(1);
429+ pcg=(unsigned int*)g_pcg_font;
430+ // 0 <= ascii <= 0xff
431+ ascii&=0xff;
432+ // Update font data
433+ ascii<<=1;
434+ pcg[ascii]=(fontdata1>>24)|((fontdata1&0xff0000)>>8)|((fontdata1&0xff00)<<8)|(fontdata1<<24);
435+ pcg[ascii+1]=(fontdata2>>24)|((fontdata2&0xff0000)>>8)|((fontdata2&0xff00)<<8)|(fontdata2<<24);
436+}
437+
438+void lib_usegraphic(int mode){
439+ usegraphic(mode);
440+ // Move current point to (0,0)
441+ g_prev_x=g_prev_y=0;
442+}
443+void lib_wait(int period){
444+ int i;
445+ unsigned short dcount;
446+ for(i=0;i<period;i++){
447+ dcount=drawcount;
448+ while(dcount==drawcount){
449+ asm (WAIT);
450+ check_break();
451+ }
452+ }
453+}
454+
455+int lib_graphic(int v0,enum functions func){
456+ unsigned char b;
457+ int x1=g_libparams[1];
458+ int y1=g_libparams[2];
459+ int x2=g_libparams[3];
460+ int y2=g_libparams[4];
461+ // Disable if graphic area is not defined.
462+ if (!g_graphic_area) return;
463+ // If C is omitted in parameters, use current color.
464+ if (v0==-1) {
465+ v0=g_gcolor;
466+ }
467+ // If X1 or Y1 is 0x80000000, use the previous values.
468+ if (x1==0x80000000) x1=g_prev_x;
469+ if (y1==0x80000000) y1=g_prev_y;
470+ switch(func){
471+ case FUNC_POINT:// X1,Y1
472+ g_prev_x=x1;
473+ g_prev_y=y1;
474+ break;
475+ case FUNC_PSET:// X1,Y1[,C]
476+ g_pset(x1,y1,v0);
477+ g_prev_x=x1;
478+ g_prev_y=y1;
479+ break;
480+ case FUNC_LINE:// X1,Y1,X2,Y2[,C]
481+ if (y1==y2) g_hline(x1,x2,y1,v0);
482+ else g_gline(x1,y1,x2,y2,v0);
483+ g_prev_x=x2;
484+ g_prev_y=y2;
485+ break;
486+ case FUNC_BOXFILL:// X1,Y1,X2,Y2[,C]
487+ g_boxfill(x1,y1,x2,y2,v0);
488+ g_prev_x=x2;
489+ g_prev_y=y2;
490+ break;
491+ case FUNC_CIRCLE:// X1,Y1,R[,C]
492+ g_circle(x1,y1,x2,v0);
493+ g_prev_x=x1;
494+ g_prev_y=y1;
495+ break;
496+ case FUNC_CIRCLEFILL:// X1,Y1,R[,C]
497+ g_circlefill(x1,y1,x2,v0);
498+ g_prev_x=x1;
499+ g_prev_y=y1;
500+ break;
501+ case FUNC_GPRINT:// X1,Y1,C,BC,S$
502+ g_printstr(x1,y1,x2,y2,(unsigned char*)v0);
503+ // Move current X,Y according to the string
504+ while(b=((unsigned char*)v0)[0]){
505+ v0++;
506+ if (b==0x0d) {
507+ x1=0;
508+ y1+=8;
509+ } else {
510+ x1+=8;
511+ }
512+ }
513+ g_prev_x=x1;
514+ g_prev_y=y1;
515+ break;
516+ case FUNC_PUTBMP2:// X1,Y1,M,N,BMP(label)
517+ // Search CDATA
518+ // It starts from either 0x00000020,0x00000021,0x00000022, or 0x00000023.
519+ while((((unsigned int*)v0)[0]&0xfffffffc)!=0x00000020) v0+=4;
520+ // CDATA starts from next word.
521+ // MLB 3 bytes show skip byte(s).
522+ v0+=4+(((unsigned int*)v0)[0]&0x03);
523+ // Contunue to FUNC_PUTBMP.
524+ case FUNC_PUTBMP:// X1,Y1,M,N,BMP(pointer)
525+ g_putbmpmn(x1,y1,x2,y2,(const unsigned char*)v0);
526+ g_prev_x=x1;
527+ g_prev_y=y1;
528+ break;
529+ case FUNC_GCOLOR:// (X1,Y1)
530+ v0=g_color(x1,y1);
531+ break;
532+ default:
533+ break;
534+ }
535+ return v0;
536+}
537+
538+void lib_var_push(int a0, int a1, int* sp){
539+ // Note that sp[1] is used for string return address
540+ // sp[2] can be used to store flags
541+ // sp[3] etc can be used to store variable values
542+ int i,params;
543+ unsigned char varnum;
544+ unsigned int strflags=0;
545+ int stack=3;
546+ for(i=0;i<8;i++){
547+ // Prepare parameter
548+ switch(i){
549+ case 0:
550+ params=a0;
551+ break;
552+ case 4:
553+ params=a1;
554+ break;
555+ default:
556+ break;
557+ }
558+ // Get variable number
559+ varnum=params&0xff;
560+ params>>=8;
561+ if (varnum==0) break; // No more variable. End the loop.
562+ varnum--;
563+ sp[stack++]=g_var_mem[varnum];
564+ if (g_var_size[varnum] && g_var_mem[varnum]==(int)(&g_var_pointer[varnum])) {
565+ // strflags change using varnum
566+ strflags|=1<<i;
567+ // Copy to VAR_BLOCK
568+ move_to_perm_block(varnum);
569+ }
570+ // Clear variable
571+ g_var_mem[varnum]=0;
572+ }
573+ // Store string flags
574+ sp[2]=strflags;
575+}
576+
577+void lib_var_pop(int a0, int a1, int* sp){
578+ // Note that sp is 4 bytes larger than that in lib_var_push
579+ // sp[1] was used to store flags
580+ // sp[2] etc can be used to store variable values
581+ int i,params;
582+ unsigned char varnum;
583+ int stack=2;
584+ unsigned int strflags=sp[1];
585+ for(i=0;i<8;i++){
586+ // Prepare parameter
587+ switch(i){
588+ case 0:
589+ params=a0;
590+ break;
591+ case 4:
592+ params=a1;
593+ break;
594+ default:
595+ break;
596+ }
597+ // Get variable number
598+ varnum=params&0xff;
599+ params>>=8;
600+ if (varnum==0) break; // No more variable. End the loop.
601+ varnum--;
602+ g_var_mem[varnum]=sp[stack++];
603+ if (strflags&(1<<i)) {
604+ // Restore from VAR_BLOCK
605+ move_from_perm_block(varnum);
606+ }
607+ }
608+}
609+
610+
611+char* lib_sprintf(char* format, int data){
612+ char* str;
613+ int i;
614+ char temp[4];
615+ if (!format) format="%g";
616+ i=snprintf((char*)(&temp[0]),4,format,data)+1;
617+ str=alloc_memory((i+3)/4,-1);
618+ snprintf(str,i,format,data);
619+ return str;
620+}
621+
622+int lib_floatfuncs(int ia0,int iv0,enum functions a1){
623+ volatile float a0,v0;
624+ ((int*)(&a0))[0]=ia0;
625+ ((int*)(&v0))[0]=iv0;
626+ switch(a1){
627+ case FUNC_FLOAT:
628+ v0=(float)iv0;
629+ break;
630+ case FUNC_INT:
631+ return (int)v0;
632+ case FUNC_VALSHARP:
633+ v0=strtof((const char*)iv0,0);
634+ break;
635+ case FUNC_SIN:
636+ v0=sinf(v0);
637+ break;
638+ case FUNC_COS:
639+ v0=cosf(v0);
640+ break;
641+ case FUNC_TAN:
642+ v0=tanf(v0);
643+ break;
644+ case FUNC_ASIN:
645+ v0=asinf(v0);
646+ break;
647+ case FUNC_ACOS:
648+ v0=acosf(v0);
649+ break;
650+ case FUNC_ATAN:
651+ v0=atanf(v0);
652+ break;
653+ case FUNC_ATAN2:
654+ v0=atan2f(v0,a0);
655+ break;
656+ case FUNC_SINH:
657+ v0=sinhf(v0);
658+ break;
659+ case FUNC_COSH:
660+ v0=coshf(v0);
661+ break;
662+ case FUNC_TANH:
663+ v0=tanhf(v0);
664+ break;
665+ case FUNC_EXP:
666+ v0=expf(v0);
667+ break;
668+ case FUNC_LOG:
669+ v0=logf(v0);
670+ break;
671+ case FUNC_LOG10:
672+ v0=log10f(v0);
673+ break;
674+ case FUNC_POW:
675+ v0=powf(v0,a0);
676+ break;
677+ case FUNC_SQRT:
678+ v0=sqrtf(v0);
679+ break;
680+ case FUNC_CEIL:
681+ v0=ceilf(v0);
682+ break;
683+ case FUNC_FLOOR:
684+ v0=floorf(v0);
685+ break;
686+ case FUNC_FABS:
687+ v0=fabsf(v0);
688+ break;
689+ case FUNC_MODF:
690+ v0=modff(v0,(void*)&a0);
691+ break;
692+ case FUNC_FMOD:
693+ v0=fmodf(v0,a0);
694+ break;
695+ default:
696+ err_unknown();
697+ break;
698+ }
699+ return ((int*)(&v0))[0];
700+};
701+
702+int* lib_dim(int varnum, int argsnum, int* sp){
703+ int i,j;
704+ static int* heap;
705+ // Calculate total length.
706+ int len=0; // Total length
707+ int size=1; // Size of current block
708+ for(i=1;i<=argsnum;i++){
709+ size*=sp[i]+1;
710+ len+=size;
711+ }
712+ // Allocate memory
713+ heap=calloc_memory(len,varnum);
714+ // Construct pointers
715+ len=0;
716+ size=1;
717+ for(i=1;i<argsnum;i++){
718+ size*=sp[i]+1;
719+ for(j=0;j<size;j++){
720+ heap[len+j]=(int)&heap[len+size+(sp[i+1]+1)*j];
721+ }
722+ len+=size;
723+ }
724+ return heap;
725+};
726+
727+int lib_file_textlen(FSFILE* fhandle){
728+ char buff[128];
729+ int i,textlen,len,seek;
730+ seek=FSftell(fhandle);
731+ len=FSfread(&buff[0],1,128,fhandle);
732+ textlen=0;
733+ for(i=0;i<len-1;i++){ // Read 127 bytes for supporting CRLF
734+ if (buff[i]==0x0d) {
735+ if (i<len && buff[i+1]==0x0a) i++;
736+ break;
737+ } else if (buff[i]==0x0a) {
738+ break;
739+ }
740+ if (i==len-2) {
741+ // reached the end of buffer. Read next 127 bytes
742+ textlen+=127;
743+ buff[0]=buff[127];
744+ len=FSfread(&buff[1],1,127,fhandle);
745+ // Continue with i=0
746+ i=-1;
747+ }
748+ }
749+ // The last return code must be included to caluclate total length.
750+ textlen+=i+1;
751+ // Return to original position
752+ FSfseek(fhandle,seek,SEEK_SET);
753+ return textlen;
754+}
755+
756+int lib_file(enum functions func, int a0, int a1, int v0){
757+ static FSFILE* s_fhandle[2]={0,0};
758+ static char activefhandle=0;
759+ static int numinline=0;
760+ FSFILE* fhandle=0;
761+ int i;
762+ int buff[1];
763+ char* str;
764+ if (activefhandle) fhandle=s_fhandle[activefhandle-1];
765+ switch(func){
766+ case FUNC_FINIT:
767+ // This function is not BASIC statement/function but used from
768+ // running routine.
769+ for(i=0;i<2;i++){
770+ if (s_fhandle[i]) FSfclose(s_fhandle[i]);
771+ s_fhandle[i]=0;
772+ }
773+ activefhandle=0;
774+ numinline=0;
775+ break;
776+ case FUNC_FOPEN: // Return 0 when called as a function.
777+ case FUNC_FOPENST: // Stop with error when called as a statement.
778+ activefhandle=0;
779+ // Check if file handle is free to use, first.
780+ switch(v0){
781+ case 0:
782+ // File handle was not designated
783+ // Force handle=1 and continue to following cases.
784+ v0=1;
785+ case 1:
786+ case 2:
787+ // File handle was designated
788+ // Check if not used yet.
789+ if (s_fhandle[v0-1]) {
790+ // This file handle has been occupied.
791+ err_file();
792+ return 0;
793+ }
794+ // OK. This file handle can be asigned for new file opened.
795+ break;
796+ default:
797+ err_invalid_param();
798+ return 0;
799+ }
800+ // Open a file
801+ fhandle=FSfopen ((const char*) a0, (const char*) a1);
802+ if (!fhandle) {
803+ if (func==FUNC_FOPENST) err_file();
804+ return 0;
805+ }
806+ // The file is succesfully opened. Asign file handle.
807+ s_fhandle[v0-1]=fhandle;
808+ activefhandle=v0;
809+ return v0;
810+ case FUNC_FILE:
811+ switch(v0){
812+ case 1:
813+ case 2:
814+ if (s_fhandle[v0]) {
815+ activefhandle=v0;
816+ break;
817+ }
818+ default:
819+ err_invalid_param();
820+ }
821+ break;
822+ case FUNC_FCLOSE:
823+ switch(v0){
824+ case 0:
825+ break;
826+ case 1:
827+ case 2:
828+ if (s_fhandle[v0-1]) activefhandle=v0;
829+ if (activefhandle) fhandle=s_fhandle[activefhandle-1];
830+ break;
831+ default:
832+ err_invalid_param();
833+ }
834+ if (fhandle) {
835+ FSfclose(fhandle);
836+ s_fhandle[activefhandle-1]=0;
837+ }
838+ activefhandle=0;
839+ break;
840+ case FUNC_FINPUT:
841+ if (fhandle) {
842+ // Determine text length if called without parameter
843+ if (v0==0) v0=lib_file_textlen(fhandle);
844+ // Allocate temporary area for string
845+ str=alloc_memory((v0+1+3)/4,-1);
846+ // Read from SD card
847+ v0=FSfread(str,1,v0,fhandle);
848+ // Null string at the end.
849+ str[v0]=0;
850+ return (int)str;
851+ } else {
852+ err_file();
853+ return (int)"";
854+ }
855+ case FUNC_FPRINTSTR:
856+ // Like lib_printstr()
857+ for(i=0;((char*)v0)[i];i++);
858+ if (fhandle) {
859+ if (!FSfwrite((char*)v0,1,i,fhandle)) err_file();
860+ } else err_file();
861+ numinline+=i;
862+ break;
863+ case FUNC_FSTRING:
864+ // Like lib_string()
865+ switch(v0){
866+ case 0:
867+ // CR
868+ lib_file(FUNC_FPRINTSTR,a0,a1,(int)"\r\n");
869+ numinline=0;
870+ break;
871+ case 1:
872+ // ,
873+ i=rem10_32(numinline);
874+ lib_file(FUNC_FPRINTSTR,a0,a1,(int)(" "+i));
875+ break;
876+ default:
877+ break;
878+ }
879+ break;
880+ case FUNC_FGET:
881+ if (fhandle) return FSfread((void*)a0,1,v0,fhandle);
882+ err_file();
883+ break;
884+ case FUNC_FPUT:
885+ if (fhandle) return FSfwrite((void*)a0,1,v0,fhandle);
886+ err_file();
887+ break;
888+ case FUNC_FGETC:
889+ if (fhandle) {
890+ // Note: Little endian.
891+ if (FSfread((void*)&buff[0],1,1,fhandle)) return buff[0]&0xff;
892+ else return -1;
893+ }
894+ err_file();
895+ break;
896+ case FUNC_FPUTC:
897+ if (fhandle) {
898+ // Note: Little endian.
899+ buff[0]=v0;
900+ return FSfwrite((void*)&buff[0],1,1,fhandle);
901+ }
902+ err_file();
903+ break;
904+ case FUNC_FSEEK:
905+ if (fhandle) return FSfseek(fhandle,v0,SEEK_SET);
906+ err_file();
907+ break;
908+ case FUNC_FTELL:
909+ if (fhandle) return FSftell(fhandle);
910+ err_file();
911+ break;
912+ case FUNC_FLEN:
913+ if (fhandle) return fhandle->size;
914+ err_file();
915+ break;
916+ case FUNC_FEOF:
917+ if (fhandle) return (fhandle->size<=FSftell(fhandle)) ? 1:0;
918+ err_file();
919+ break;
920+ case FUNC_FREMOVE:
921+ return FSremove((const char *)v0);
922+ default:
923+ err_unknown();
924+ }
925+ return v0;
926+}
927+
928+int _call_library(int a0,int a1,int a2,enum libs a3);
929+
930+void call_library(void){
931+ // Store s6 in g_s6
932+ asm volatile("la $a2,%0"::"i"(&g_s6));
933+ asm volatile("sw $s6,0($a2)");
934+ // Copy $v0 to $a2 as 3rd argument of function
935+ asm volatile("addu $a2,$v0,$zero");
936+ // Store sp in g_libparams
937+ asm volatile("la $v0,%0"::"i"(&g_libparams));
938+ asm volatile("sw $sp,0($v0)");
939+ // Jump to main routine
940+ asm volatile("j _call_library");
941+}
942+
943+int _call_library(int a0,int a1,int v0,enum libs a3){
944+ // usage: call_lib_code(LIB_XXXX);
945+ // Above code takes 2 words.
946+ check_break();
947+ switch(a3 & LIB_MASK){
948+ case LIB_FLOAT:
949+ return lib_float(a0,v0,(enum operator)(a3 & OP_MASK)); // see operator.c
950+ case LIB_FLOATFUNCS:
951+ return lib_floatfuncs(a0,v0,(enum functions)(a3 & FUNC_MASK));
952+ case LIB_STRNCMP:
953+ return strncmp((char*)g_libparams[1],(char*)g_libparams[2],v0);
954+ case LIB_MIDSTR:
955+ return (int)lib_midstr(a1,v0,a0);
956+ case LIB_RND:
957+ return (int)lib_rnd();
958+ case LIB_DEC:
959+ return (int)lib_dec(v0);
960+ case LIB_HEX:
961+ return (int)lib_hex(v0,a0);
962+ case LIB_CHR:
963+ return (int)lib_chr(v0);
964+ case LIB_VAL:
965+ return lib_val((char*)v0);
966+ case LIB_LETSTR:
967+ lib_let_str((char*)v0,a0);
968+ return;
969+ case LIB_CONNECT_STRING:
970+ return (int)lib_connect_string((char*)a0, (char*)v0);
971+ case LIB_STRING:
972+ lib_string(v0);
973+ return v0;
974+ case LIB_PRINTSTR:
975+ printstr((char*)v0);
976+ return v0;
977+ case LIB_GRAPHIC:
978+ return lib_graphic(v0, (enum functions)(a3 & FUNC_MASK));
979+ case LIB_SPRINTF:
980+ return (int)lib_sprintf((char*)v0,a0);
981+ case LIB_VAR_PUSH:
982+ lib_var_push(a0,a1,g_libparams);
983+ return v0;
984+ case LIB_VAR_POP:
985+ lib_var_pop(a0,a1,g_libparams);
986+ return v0;
987+ case LIB_SCROLL:
988+ scroll(g_libparams[1],v0);
989+ return v0;
990+ case LIB_FILE:
991+ return lib_file((enum functions)(a3 & FUNC_MASK),g_libparams[1],g_libparams[2],v0);
992+ case LIB_KEYS:
993+ return lib_keys(v0);
994+ case LIB_INKEY:
995+ return (int)lib_inkey(v0);
996+ case LIB_CURSOR:
997+ setcursor(g_libparams[1],v0,cursorcolor);
998+ return v0;
999+ case LIB_SOUND:
1000+ set_sound((unsigned long*)v0,a0);
1001+ return v0;
1002+ case LIB_MUSICFUNC:
1003+ return musicRemaining(a0);
1004+ case LIB_MUSIC:
1005+ set_music((char*)v0,a0);
1006+ return v0;
1007+ case LIB_PLAYWAVE:
1008+ play_wave((char*)g_libparams[1],v0);
1009+ return v0;
1010+ case LIB_PLAYWAVEFUNC:
1011+ return waveRemaining(v0);
1012+ case LIB_SETDRAWCOUNT:
1013+ drawcount=(v0&0x0000FFFF);
1014+ return v0;
1015+ case LIB_DRAWCOUNT:
1016+ return drawcount;
1017+ case LIB_SYSTEM:
1018+ return lib_system(a0, a1 ,v0, a3, g_gcolor, g_prev_x, g_prev_y);
1019+ case LIB_RESTORE:
1020+ return lib_read(0,v0);
1021+ case LIB_RESTORE2:
1022+ return lib_read(1,v0);
1023+ case LIB_READ:
1024+ return lib_read(0,0);
1025+ case LIB_CREAD:
1026+ return lib_read(1,0);
1027+ case LIB_LABEL:
1028+ return (int)lib_label(v0);
1029+ case LIB_INPUT:
1030+ return (int)lib_input();
1031+ case LIB_USEGRAPHIC:
1032+ lib_usegraphic(v0);
1033+ return v0;
1034+ case LIB_USEPCG:
1035+ lib_usepcg(v0);
1036+ return v0;
1037+ case LIB_PCG:
1038+ lib_pcg(g_libparams[1],g_libparams[2],v0);
1039+ return v0;
1040+ case LIB_BGCOLOR: // BGCOLOR R,G,B
1041+ set_bgcolor(v0,g_libparams[1],g_libparams[2]); //set_bgcolor(b,r,g);
1042+ return v0;
1043+ case LIB_PALETTE: // PALETTE N,R,G,B
1044+ set_palette(g_libparams[1],v0,g_libparams[2],g_libparams[3]); // set_palette(n,b,r,g);
1045+ return v0;
1046+ case LIB_GPALETTE:// GPALETTE N,R,G,B
1047+ if (g_graphic_area) g_set_palette(g_libparams[1],v0,g_libparams[2],g_libparams[3]); // g_set_palette(n,b,r,g);
1048+ return v0;
1049+ case LIB_CLS:
1050+ clearscreen();
1051+ return v0;
1052+ case LIB_GCLS:
1053+ if (g_graphic_area) g_clearscreen();
1054+ g_prev_x=g_prev_y=0;
1055+ return v0;
1056+ case LIB_WIDTH:
1057+ videowidth(v0);
1058+ return v0;
1059+ case LIB_COLOR:
1060+ setcursorcolor(v0);
1061+ return v0;
1062+ case LIB_GCOLOR:
1063+ g_gcolor=v0;
1064+ return v0;
1065+ case LIB_WAIT:
1066+ lib_wait(v0);
1067+ return v0;
1068+ case LIB_CLEAR:
1069+ lib_clear();
1070+ return v0;
1071+ case LIB_DIM:
1072+ return (int)lib_dim(a0,a1,(int*)v0);
1073+#ifdef __DEBUG
1074+ case LIB_DEBUG:
1075+ asm volatile("nop");
1076+ return v0;
1077+#endif
1078+ case LIB_DIV0:
1079+ err_div_zero();
1080+ return v0;
1081+ default:
1082+ err_unknown();
1083+ return v0;
1084+ }
1085+}
\ No newline at end of file
--- mips/trunk/megalopa/statement.c (nonexistent)
+++ mips/trunk/megalopa/statement.c (revision 268)
@@ -0,0 +1,1637 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by Katsumi.
4+ http://hp.vector.co.jp/authors/VA016157/
5+ kmorimatsu@users.sourceforge.jp
6+*/
7+
8+#include "api.h"
9+#include "compiler.h"
10+
11+char* rem_statement(){
12+ if (g_source[g_srcpos-4]<0x20) {
13+ // This line contains only "REM" statement
14+ // Delete $s6-setting command if exists.
15+ if ((g_object[g_objpos-1]&0xffff0000)==0x34160000) g_objpos--;
16+ }
17+ while(0x20<=g_source[g_srcpos]){
18+ g_srcpos++;
19+ }
20+ return 0;
21+}
22+
23+char* sound_statement(){
24+ char *err;
25+ err=get_label();
26+ if (err) return err;
27+ if (g_label) {
28+ // Label/number is constant.
29+ // Linker will change following codes later.
30+ // Note that 0x0814xxxx and 0x0815xxxx are specific codes for these.
31+ check_obj_space(2);
32+ g_object[g_objpos++]=0x08140000|((g_label>>16)&0x0000FFFF); // lui v0,xxxx
33+ g_object[g_objpos++]=0x08150000|(g_label&0x0000FFFF); // ori v0,v0,xxxx
34+ } else {
35+ // Label/number will be dynamically set when executing code.
36+ err=get_value();
37+ if (err) return err;
38+ call_lib_code(LIB_LABEL);
39+ }
40+ // 2nd param is optional
41+ next_position();
42+ if (g_source[g_srcpos]==',') {
43+ g_srcpos++;
44+ check_obj_space(2);
45+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
46+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
47+ err=get_value();
48+ if (err) return err;
49+ check_obj_space(3);
50+ g_object[g_objpos++]=0x00402021; // addu a0,v0,zero
51+ g_object[g_objpos++]=0x8FA20004; // lw v0,4(sp)
52+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
53+ } else {
54+ // Set 3 if omitted
55+ check_obj_space(1);
56+ g_object[g_objpos++]=0x24040003; // addiu a0,zero,xx
57+ }
58+ call_lib_code(LIB_SOUND);
59+ return 0;
60+}
61+char* music_statement(){
62+ char *err;
63+ err=get_string();
64+ if (err) return err;
65+ // 2nd param is optional
66+ next_position();
67+ if (g_source[g_srcpos]==',') {
68+ g_srcpos++;
69+ check_obj_space(2);
70+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
71+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
72+ err=get_value();
73+ if (err) return err;
74+ check_obj_space(3);
75+ g_object[g_objpos++]=0x00402021; // addu a0,v0,zero
76+ g_object[g_objpos++]=0x8FA20004; // lw v0,4(sp)
77+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
78+ } else {
79+ // Set 3 if omitted
80+ check_obj_space(1);
81+ g_object[g_objpos++]=0x24040003; // addiu a0,zero,xx
82+ }
83+ call_lib_code(LIB_MUSIC);
84+ return 0;
85+}
86+
87+char* exec_statement(){
88+ char *err;
89+ char b1;
90+ int i,prevpos;
91+ b1=g_source[g_srcpos];
92+ while('0'<=b1 && b1<='9' || b1=='-' || b1=='$'){
93+ prevpos=g_objpos;
94+ g_valueisconst=1;
95+ err=get_simple_value();
96+ if (!g_valueisconst) err=ERR_SYNTAX;
97+ if (err) return err;
98+ check_obj_space(1);
99+ g_objpos=prevpos;
100+ g_object[g_objpos++]=g_intconst;
101+ next_position();
102+ b1=g_source[g_srcpos];
103+ if (b1!=',') break;
104+ g_srcpos++;
105+ next_position();
106+ b1=g_source[g_srcpos];
107+ if (b1==0x0d || b1==0x0a) {
108+ // Multiline DATA/EXEC statement
109+ g_line++;
110+ g_fileline++;
111+ if (b1==0x0D && g_source[g_srcpos+1]==0x0A) g_srcpos++;
112+ g_srcpos++;
113+ // Maintain at least 256 characters in cache.
114+ if (256<=g_srcpos) read_file(256);
115+ next_position();
116+ b1=g_source[g_srcpos];
117+ }
118+ }
119+ return 0;
120+}
121+
122+char* cdata_statement(){
123+ // 0x00000020, 0x00000021, 0x00000022, and 0x00000023 (add/addu/sub/subu zero,zero,zero)
124+ // are the sign of data region
125+ int beginpos,prevpos;
126+ char* err;
127+ char b1;
128+ char* cpy;
129+ int shift=0;
130+ int i=0;
131+ beginpos=g_objpos;
132+ check_obj_space(2);
133+ g_object[g_objpos++]=0x04110000; // bgezal zero,xxxx
134+ g_object[g_objpos++]=0x00000020; // add zero,zero,zero
135+ next_position();
136+ b1=g_source[g_srcpos];
137+ while('0'<=b1 && b1<='9' || b1=='-' || b1=='$'){
138+ prevpos=g_objpos;
139+ g_valueisconst=1;
140+ err=get_simple_value();
141+ if (!g_valueisconst) err=ERR_SYNTAX;
142+ if (g_intconst<0x00 || 0xff<g_intconst) err=ERR_SYNTAX;
143+ if (err) return err;
144+ g_objpos=prevpos;
145+ i|=g_intconst<<shift;
146+ shift+=8;
147+ if (32<=shift) {
148+ check_obj_space(1);
149+ g_object[g_objpos++]=i;
150+ shift=0;
151+ i=0;
152+ }
153+ next_position();
154+ b1=g_source[g_srcpos];
155+ if (b1!=',') break;
156+ g_srcpos++;
157+ next_position();
158+ b1=g_source[g_srcpos];
159+ if (b1==0x0d || b1==0x0a) {
160+ // Multiline CDATA statement
161+ g_line++;
162+ g_fileline++;
163+ if (b1==0x0D && g_source[g_srcpos+1]==0x0A) g_srcpos++;
164+ g_srcpos++;
165+ // Maintain at least 256 characters in cache.
166+ if (256<=g_srcpos) read_file(256);
167+ next_position();
168+ b1=g_source[g_srcpos];
169+ }
170+ }
171+ // Write the last 1-3 bytes and shift data if total # is not multipes of 4.
172+ if (0<shift) {
173+ // Convert shift value from bit-shift to data byte-shift.
174+ shift=4-shift/8;
175+ check_obj_space(1);
176+ g_object[g_objpos++]=i;
177+ for(cpy=(char*)&g_object[g_objpos]-1;(char*)&g_object[beginpos+2]<cpy;cpy--){
178+ cpy[0]=cpy[0-shift];
179+ }
180+ }
181+ // Determine the size of data
182+ i=g_objpos-beginpos-1;
183+ g_object[beginpos] =0x04110000|i; // bgezal zero,xxxx
184+ g_object[beginpos+1]=0x00000020|shift; // add zero,zero,zero
185+ return 0;
186+}
187+
188+char* data_statement(){
189+ // 0x00000020, 0x00000021, 0x00000022, and 0x00000023 (add/addu/sub/subu zero,zero,zero)
190+ // are the sign of data region
191+ int i,prevpos;
192+ char* err;
193+ while(1){
194+ prevpos=g_objpos;
195+ check_obj_space(2);
196+ g_object[g_objpos++]=0x04110000; // bgezal zero,xxxx
197+ g_object[g_objpos++]=0x00000020; // add zero,zero,zero
198+ next_position();
199+ if (g_source[g_srcpos]=='"') {
200+ // Constant string
201+ // Store pointer to string. This is 3 words bellow of current position
202+ g_object[g_objpos]=(int)(&g_object[g_objpos+3]);
203+ g_objpos++;
204+ g_object[prevpos]=0x04110002; // bgezal zero,xxxx
205+ err=simple_string();
206+ if (err) return err;
207+ next_position();
208+ if (g_source[g_srcpos]==',') {
209+ g_srcpos++;
210+ continue;
211+ }
212+ return 0;
213+ }
214+ err=exec_statement();
215+ if (err) return err;
216+ // Determine the size of data
217+ i=g_objpos-prevpos-1;
218+ g_object[prevpos]=0x04110000|i; // bgezal zero,xxxx
219+ if (g_source[g_srcpos]=='"') {
220+ // Constant string
221+ continue;
222+ }
223+ return 0;
224+ }
225+}
226+
227+char* clear_statement(){
228+ call_lib_code(LIB_CLEAR);
229+ return 0;
230+}
231+
232+char* poke_statement(){
233+ char* err;
234+ err=get_value();
235+ if (err) return err;
236+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
237+ g_srcpos++;
238+ check_obj_space(2);
239+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
240+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
241+ err=get_value();
242+ if (err) return err;
243+ check_obj_space(3);
244+ g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp)
245+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
246+ g_object[g_objpos++]=0xA0620000; // sb v0,0(v1)
247+ return 0;
248+}
249+
250+char* dim_statement(){
251+ char* err;
252+ char b1;
253+ int i;
254+ int spos;
255+ int stack;
256+ while(1){
257+ stack=0;
258+ next_position();
259+ i=get_var_number();
260+ if (i<0) return ERR_SYNTAX;
261+ if (g_source[g_srcpos]=='#') g_srcpos++;
262+ next_position();
263+ if (g_source[g_srcpos]!='(') return ERR_SYNTAX;
264+ check_obj_space(1);
265+ spos=g_objpos++; // addiu sp,sp,xxxx
266+ do {
267+ g_srcpos++;
268+ err=get_value();
269+ if (err) return err;
270+ stack+=4;
271+ check_obj_space(1);
272+ g_object[g_objpos++]=0xAFA20000|stack; // sw v0,8(sp)
273+ } while (g_source[g_srcpos]==',');
274+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
275+ g_srcpos++;
276+ check_obj_space(3);
277+ g_object[g_objpos++]=0x24040000|(i); // addiu a0,zero,xx
278+ g_object[g_objpos++]=0x24050000|(stack/4); // addiu a1,zero,xxxx
279+ g_object[g_objpos++]=0x03A01025; // or v0,sp,zero
280+ call_lib_code(LIB_DIM);
281+ // Stack -/+
282+ check_obj_space(1);
283+ g_object[g_objpos++]=0x27BD0000|stack; // addiu sp,sp,xxxx
284+ stack=(0-stack)&0x0000FFFF;
285+ g_object[spos]=0x27BD0000|stack; // addiu sp,sp,xxxx
286+ next_position();
287+ if (g_source[g_srcpos]!=',') break;
288+ g_srcpos++;
289+ }
290+ return 0;
291+}
292+
293+char* label_statement(){
294+ char* err;
295+ char b1;
296+ b1=g_source[g_srcpos];
297+ if (b1<'A' || 'Z'<b1) return ERR_SYNTAX; // Number is not allowed here.
298+ err=get_label();
299+ if (err) return err;
300+ // Check existing label with the same name here.
301+ if (search_label(g_label)) {
302+ // Error: duplicate labels
303+ printstr("Label ");
304+ printstr(resolve_label(g_label));
305+ return ERR_MULTIPLE_LABEL;
306+ }
307+ check_obj_space(2);
308+ g_object[g_objpos++]=0x3C160000|((g_label>>16)&0x0000FFFF); //lui s6,yyyy;
309+ g_object[g_objpos++]=0x36D60000|(g_label&0x0000FFFF); //ori s6,s6,zzzz;
310+ return 0;
311+}
312+
313+char* restore_statement(){
314+ char* err;
315+ err=get_label();
316+ if (err) return err;
317+ if (g_label) {
318+ // Constant label/number
319+ // Use 32 bit mode also for values<65536
320+ // This code will be replaced to code for v0 for pointer in linker.
321+ check_obj_space(2);
322+ g_object[g_objpos++]=0x3C020000|(g_label>>16); // lui v0,xxxx
323+ g_object[g_objpos++]=0x34420000|(g_label&0x0000FFFF); // ori v0,v0,xxxx
324+ } else {
325+ // Dynamic number
326+ err=get_value();
327+ if (err) return err;
328+ }
329+ call_lib_code(LIB_RESTORE);
330+ return 0;
331+}
332+
333+char* gosub_statement_sub(){
334+ char* err;
335+ err=get_label();
336+ if (err) return err;
337+ if (g_label) {
338+ // Label/number is constant.
339+ // Linker will change following codes later.
340+ // Note that 0x0812xxxx and 0x0813xxxx are specific codes for these.
341+ check_obj_space(6);
342+ g_object[g_objpos++]=0x04130003; // bgezall zero,label1
343+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
344+ g_object[g_objpos++]=0x10000003; // beq zero,zero,label2
345+ g_object[g_objpos++]=0x08120000|((g_label>>16)&0x0000FFFF); // nop
346+ // label1:
347+ g_object[g_objpos++]=0x08130000|(g_label&0x0000FFFF); // j xxxx
348+ g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp)
349+ // label2:
350+ } else {
351+ // Label/number will be dynamically set when executing code.
352+ err=get_value();
353+ if (err) return err;
354+ call_lib_code(LIB_LABEL);
355+ check_obj_space(6);
356+ g_object[g_objpos++]=0x04130003; // bgezall zero,label1
357+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
358+ g_object[g_objpos++]=0x10000003; // beq zero,zero,label2
359+ g_object[g_objpos++]=0x00000000; // nop
360+ // label1:
361+ g_object[g_objpos++]=0x00400008; // jr v0
362+ g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp)
363+ // label2:
364+ }
365+ return 0;
366+}
367+
368+char* gosub_statement(){
369+ char* err;
370+ int opos,spos,stack;
371+ opos=g_objpos;
372+ spos=g_srcpos;
373+ err=gosub_statement_sub();
374+ if (err) return err;
375+ next_position();
376+ // If there is no 2nd argument, return.
377+ if (g_source[g_srcpos]!=',') return 0;
378+
379+ // There is (at least) 2nd argument.
380+ // Rewind object and construct argument-creating routine.
381+ g_objpos=opos;
382+ stack=4;
383+ g_object[g_objpos++]=0x27BD0000; // addiu sp,sp,-xx
384+ do {
385+ g_srcpos++;
386+ stack+=4;
387+ err=get_stringFloatOrValue();
388+ if (err) return err;
389+ check_obj_space(1);
390+ g_object[g_objpos++]=0xAFA20000|stack; // sw v0,xx(sp)
391+ next_position();
392+ } while(g_source[g_srcpos]==',');
393+ check_obj_space(2);
394+ g_object[g_objpos++]=0xAFB50004; // sw s5,4(sp)
395+ g_object[g_objpos++]=0x03A0A821; // addu s5,sp,zero
396+ g_object[opos]|=((0-stack)&0xFFFF); // addiu sp,sp,-xx (See above)
397+ // Rewind source and construct GOSUB routine again.
398+ opos=spos;
399+ spos=g_srcpos;
400+ g_srcpos=opos;
401+ err=gosub_statement_sub();
402+ if (err) return err;
403+ // Remove stack
404+ check_obj_space(2);
405+ g_object[g_objpos++]=0x8FB50004; // lw s5,4(sp)
406+ g_object[g_objpos++]=0x27BD0000|stack; // addiu sp,sp,xx
407+ // All done, go back to wright source position
408+ g_srcpos=spos;
409+ return 0;
410+}
411+
412+char* return_statement(){
413+ char* err;
414+ char b1;
415+ next_position();
416+ b1=g_source[g_srcpos];
417+ if (0x20<b1 && b1!=':') {
418+ // There is a return value.
419+ err=get_stringFloatOrValue();
420+ if (err) return err;
421+ }
422+ check_obj_space(3);
423+ g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp)
424+ g_object[g_objpos++]=0x00600008; // jr v1
425+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
426+ return 0;
427+}
428+
429+char* goto_statement(){
430+ char* err;
431+ err=get_label();
432+ if (err) return err;
433+ if (g_label) {
434+ // Label/number is constant.
435+ // Linker will change following codes later.
436+ // Note that 0x0810xxxx and 0x0811xxxx are specific codes for these.
437+ check_obj_space(2);
438+ g_object[g_objpos++]=0x08100000|((g_label>>16)&0x0000FFFF); // j xxxx
439+ g_object[g_objpos++]=0x08110000|(g_label&0x0000FFFF); // nop
440+ } else {
441+ // Label/number will be dynamically set when executing code.
442+ err=get_value();
443+ if (err) return err;
444+ call_lib_code(LIB_LABEL);
445+ check_obj_space(2);
446+ g_object[g_objpos++]=0x00400008; // jr v0
447+ g_object[g_objpos++]=0x00000000; // nop
448+ }
449+ return 0;
450+}
451+
452+char* if_statement(){
453+ char* err;
454+ int prevpos,bpos;
455+ // Get value.
456+ err=get_floatOrValue();
457+ if (err) return err;
458+ // Check "THEN"
459+ if (!nextCodeIs("THEN")) return ERR_SYNTAX;
460+ // Check if statement follows after THEN statement
461+ next_position();
462+ if (nextCodeIs("REM")) {
463+ // If REM statement follows, skip comment words.
464+ rem_statement();
465+ }
466+ if (g_source[g_srcpos]<0x20) {
467+ // End of line.
468+ // Use IF-THEN-ENDIF mode (multiple line mode)
469+ check_obj_space(3);
470+ g_object[g_objpos++]=0x30000000; // nop (see linker)
471+ g_object[g_objpos++]=0x10400000; // beq v0,zero,xxxx
472+ g_object[g_objpos++]=0x30000000; // nop (see linker)
473+ return 0;
474+ }
475+ // One line mode
476+ // If $v0=0 then skip.
477+ bpos=g_objpos;
478+ check_obj_space(2);
479+ g_object[g_objpos++]=0x10400000; // beq v0,zero,xxxx
480+ g_object[g_objpos++]=0x00000000; // nop
481+ prevpos=g_srcpos;
482+ if (statement()) {
483+ // May be label
484+ g_srcpos=prevpos;
485+ err=goto_statement();
486+ if (err) return err;
487+ } else {
488+ // Must be statement(s)
489+ while(1) {
490+ if (g_source[g_srcpos]!=':') break;
491+ g_srcpos++;
492+ err=statement();
493+ if (err) return err;
494+ }
495+ }
496+ // Check if "ELSE" exists.
497+ if (!nextCodeIs("ELSE ")) {
498+ // "ELSE" not found. This is the end of "IF" statement.
499+ // Previous branch command must jump to this position.
500+ g_object[bpos]=0x10400000|(g_objpos-bpos-1); // beq v0,zero,xxxx
501+ return 0;
502+ }
503+ // Skip after ELSE if required.
504+ check_obj_space(2);
505+ g_object[g_objpos++]=0x10000000; // beq zero,zero,xxxx
506+ g_object[g_objpos++]=0x00000000; // nop
507+ // Previous branch command must jump to this position.
508+ g_object[bpos]=0x10400000|(g_objpos-bpos-1); // beq v0,zero,xxxx
509+ bpos=g_objpos-2;
510+ // Next statement is either label or general statement
511+ prevpos=g_srcpos;
512+ if (statement()) {
513+ // May be label
514+ g_srcpos=prevpos;
515+ err=goto_statement();
516+ if (err) return err;
517+ } else {
518+ // Must be statement(s)
519+ while(1) {
520+ if (g_source[g_srcpos]!=':') break;
521+ g_srcpos++;
522+ err=statement();
523+ if (err) return err;
524+ }
525+ }
526+ // Previous branch command must jump to this position.
527+ g_object[bpos]=0x10000000|(g_objpos-bpos-1); // beq zero,zero,xxxx
528+ return 0;
529+}
530+
531+char* elseif_statement(void){
532+ // Multiple line mode
533+ char* err;
534+ g_object[g_objpos++]=0x08160100; // breakif (see linker)
535+ g_object[g_objpos++]=0x30008000; // nop (see linker)
536+ // Get value.
537+ err=get_floatOrValue();
538+ if (err) return err;
539+ // Check "THEN"
540+ if (!nextCodeIs("THEN")) return ERR_SYNTAX;
541+ // Check if statement follows after THEN statement
542+ if (nextCodeIs("REM")) {
543+ // If REM statement follows, skip comment words.
544+ rem_statement();
545+ }
546+ if (0x20<=g_source[g_srcpos]) return ERR_SYNTAX;
547+ // Statement didn't follow after THEM statement (that is correct).
548+ g_object[g_objpos++]=0x10400000; // beq v0,zero,xxxx
549+ g_object[g_objpos++]=0x30000000; // nop (see linker)
550+ return 0;
551+
552+}
553+
554+char* else_statement(void){
555+ // Multiple line mode
556+ g_object[g_objpos++]=0x08160100; // breakif (see linker)
557+ g_object[g_objpos++]=0x30008000; // nop (see linker)
558+ g_object[g_objpos++]=0x30000000; // nop (see linker)
559+ // Check if statement follows after THEN statement
560+ if (nextCodeIs("REM")) {
561+ // If REM statement follows, skip comment words.
562+ rem_statement();
563+ }
564+ if (0x20<=g_source[g_srcpos]) return ERR_SYNTAX;
565+ // Statement didn't follow after THEM statement (that is correct).
566+ return 0;
567+}
568+
569+char* endif_statement(void){
570+ // Multiple line mode
571+ g_object[g_objpos++]=0x30008000; // nop (see linker)
572+ g_object[g_objpos++]=0x30008000; // nop (see linker)
573+ // Check if statement follows after THEN statement
574+ if (nextCodeIs("REM")) {
575+ // If REM statement follows, skip comment words.
576+ rem_statement();
577+ }
578+ if (0x20<=g_source[g_srcpos]) return ERR_SYNTAX;
579+ // Statement didn't follow after THEM statement (that is correct).
580+ return 0;
581+}
582+
583+char* end_statement(void){
584+ int i;
585+ i=(int)&g_end_addr;
586+ i-=g_gp;
587+ check_obj_space(3);
588+ g_object[g_objpos++]=0x8F820000|(i&0x0000FFFF); // lw v0,xxxx(gp)
589+ g_object[g_objpos++]=0x00400008; // jr v0
590+ g_object[g_objpos++]=0x00000000; // nop
591+ return 0;
592+}
593+
594+char* let_dim_sub(int i){
595+ char* err;
596+ g_srcpos++;
597+ err=get_value();
598+ if (err) return err;
599+ check_obj_space(4);
600+ g_object[g_objpos++]=0x00021080; // sll v0,v0,0x2
601+ g_object[g_objpos++]=0x8FC30000|(i*4); // lw v1,xx(s8)
602+ g_object[g_objpos++]=0x00621821; // addu v1,v1,v0
603+ g_object[g_objpos++]=0xAFA30004; // sw v1,4(sp)
604+ while(g_source[g_srcpos]==','){
605+ g_srcpos++;
606+ err=get_value();
607+ if (err) return err;
608+ check_obj_space(4);
609+ g_object[g_objpos++]=0x00021080; // sll v0,v0,0x2
610+ g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp)
611+ g_object[g_objpos++]=0x8C630000; // lw v1,0(v1)
612+ g_object[g_objpos++]=0x00621821; // addu v1,v1,v0
613+ g_object[g_objpos++]=0xAFA30004; // sw v1,4(sp)
614+ }
615+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
616+ g_srcpos++;
617+ return 0;
618+};
619+
620+char* let_statement(){
621+ char* err;
622+ char b2,b3;
623+ int i;
624+ next_position();
625+ i=get_var_number();
626+ if (i<0) return ERR_SYNTAX;
627+ b2=g_source[g_srcpos];
628+ b3=g_source[g_srcpos+1];
629+ if (b2=='#' && b3=='(') {
630+ // Float dimension
631+ g_srcpos++;
632+ check_obj_space(1);
633+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
634+ let_dim_sub(i);
635+ next_position();
636+ if (g_source[g_srcpos]!='=') return ERR_SYNTAX;
637+ g_srcpos++;
638+ err=get_float();
639+ if (err) return err;
640+ check_obj_space(3);
641+ g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp)
642+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
643+ g_object[g_objpos++]=0xAC620000; // sw v0,0(v1)
644+ return 0;
645+ } else if (b2=='#') {
646+ // Float A-Z
647+ g_srcpos++;
648+ next_position();
649+ if (g_source[g_srcpos]!='=') return ERR_SYNTAX;
650+ g_srcpos++;
651+ err=get_float();
652+ if (err) return err;
653+ check_obj_space(1);
654+ g_object[g_objpos++]=0xAFC20000|(i*4); // sw v0,xxx(s8)
655+ return 0;
656+ } else if (b2=='$') {
657+ // String
658+ g_srcpos++;
659+ next_position();
660+ if (g_source[g_srcpos]!='=') return ERR_SYNTAX;
661+ g_srcpos++;
662+ err=get_string();
663+ if (err) return err;
664+ check_obj_space(1);
665+ g_object[g_objpos++]=0x24040000|(i); //addiu a0,zero,xx
666+ call_lib_code(LIB_LETSTR);
667+ return 0;
668+ } else if (b2=='(') {
669+ // Dimension
670+ check_obj_space(1);
671+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
672+ let_dim_sub(i);
673+ next_position();
674+ if (g_source[g_srcpos]!='=') return ERR_SYNTAX;
675+ g_srcpos++;
676+ err=get_value();
677+ if (err) return err;
678+ check_obj_space(3);
679+ g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp)
680+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
681+ g_object[g_objpos++]=0xAC620000; // sw v0,0(v1)
682+ return 0;
683+ } else {
684+ // Integer A-Z
685+ next_position();
686+ if (g_source[g_srcpos]!='=') return ERR_SYNTAX;
687+ g_srcpos++;
688+ err=get_value();
689+ if (err) return err;
690+ check_obj_space(1);
691+ g_object[g_objpos++]=0xAFC20000|(i*4); // sw v0,xxx(s8)
692+ }
693+ return 0;
694+}
695+
696+char* print_statement_main(enum libs lib_printstr, enum libs lib_string){
697+ char* err;
698+ char b1;
699+ int i;
700+ int status=0;// 1:',' 2:';' 0:none
701+ while(1){
702+ next_position();
703+ if (endOfStatement()) break;
704+ if (!strncmp(g_source+g_srcpos,"ELSE " ,5)) break;
705+ err=get_stringFloatOrValue();
706+ if (err) return err;
707+ switch(g_lastvar){
708+ case VAR_INTEGER:
709+ // Use DEC$() function.
710+ call_lib_code(LIB_DEC);
711+ break;
712+ case VAR_FLOAT:
713+ // Use FLOAT$() function.
714+ check_obj_space(2);
715+ g_object[g_objpos++]=0x00022021; //addu a0,zero,v0
716+ g_object[g_objpos++]=0x34020000; //ori v0,zero,0x0000
717+ call_lib_code(LIB_SPRINTF);
718+ break;
719+ case VAR_STRING:
720+ default:
721+ break;
722+ }
723+ // Call printstr() function
724+ // First argument is the pointer to string
725+ call_lib_code(lib_printstr);
726+ next_position();
727+ b1=g_source[g_srcpos];
728+ if (b1==',') {
729+ status=1;
730+ g_srcpos++;
731+ // Call lib_string() function for comma (,)
732+ check_obj_space(1);
733+ g_object[g_objpos++]=0x34020001; // ori v0,zero,1
734+ call_lib_code(lib_string);
735+ } else if (b1==';') {
736+ status=2;
737+ g_srcpos++;
738+ } else {
739+ status=0;
740+ }
741+ }
742+ if (status==0) {
743+ // Call lib_string() function for CR (\n)
744+ check_obj_space(1);
745+ g_object[g_objpos++]=0x34020000; // ori v0,zero,0
746+ call_lib_code(lib_string);
747+ }
748+ return 0;
749+}
750+
751+char* break_statement(){
752+ check_obj_space(2);
753+ g_object[g_objpos++]=0x08160000; // j xxxx (See link() function)
754+ g_object[g_objpos++]=0x00000000; // nop
755+ return 0;
756+}
757+
758+char* continue_statement(){
759+ check_obj_space(2);
760+ g_object[g_objpos++]=0x08160008; // j xxxx (See link() function)
761+ g_object[g_objpos++]=0x00000000; // nop
762+ return 0;
763+}
764+
765+char* for_statement(){
766+ char* err;
767+// char b1;
768+ int i;
769+ int prepos=g_srcpos;
770+ // Initialization of variable
771+// next_position();
772+// b1=g_source[g_srcpos];
773+ i=get_var_number();
774+// if (b1<'A' || 'Z'<b1) return ERR_SYNTAX;
775+ if (i<0) return ERR_SYNTAX;
776+ g_srcpos=prepos;
777+ err=let_statement();
778+ if (err) return err;
779+ // Check if "TO" exists
780+ if (!nextCodeIs("TO ")) return ERR_SYNTAX;
781+ err=get_value();
782+ if (err) return err;
783+ // Usage of stack:
784+ // 12(sp): "TO" value
785+ // 8(sp): "STEP" value
786+ // 4(sp): Address to return to in "NEXT" statement.
787+ // Store "TO" value in stack
788+ check_obj_space(2);
789+ g_object[g_objpos++]=0x0820FFF4; // addiu sp,sp,-12 (see linker)
790+ g_object[g_objpos++]=0xAFA2000C; // sw v0,12(sp)
791+ // Check if "STEP" exists
792+ g_valueisconst=1;
793+ if (nextCodeIs("STEP ")) {
794+ // "STEP" exists. Get value
795+ err=get_value();
796+ if (err) return err;
797+ } else {
798+ // "STEP" not exist. Use "1".
799+ check_obj_space(1);
800+ g_object[g_objpos++]=0x24020001; // addiu v0,zero,1
801+ g_intconst=1;
802+ }
803+ check_obj_space(14);
804+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp) (STEP value)
805+ g_object[g_objpos++]=0x04130004; // bgezall zero,check
806+// g_object[g_objpos++]=0x8FC40000|((b1-'A')*4); // lw a0,xx(s8) (current var value)
807+ g_object[g_objpos++]=0x8FC40000|(i*4); // lw a0,xx(s8) (current var value)
808+ // After executing "NEXT" statement, process reaches following line.
809+ // Update variable value by adding STEP value
810+ // Note that STEP value is loaded onto $v0 in NEXT statement
811+// g_object[g_objpos++]=0x8FC40000|((b1-'A')*4); // lw a0,xx(s8) (current var value)
812+ g_object[g_objpos++]=0x8FC40000|(i*4); // lw a0,xx(s8) (current var value)
813+ g_object[g_objpos++]=0x00822021; // addu a0,a0,v0
814+// g_object[g_objpos++]=0xAFC40000|((b1-'A')*4); // sw a0,xx(s8) (new var value)
815+ g_object[g_objpos++]=0xAFC40000|(i*4); // sw a0,xx(s8) (new var value)
816+ // Value-checking routine and storing ra in stack
817+ // check:
818+ g_object[g_objpos++]=0x8FA3000C; // lw v1,12(sp) (TO value)
819+ g_object[g_objpos++]=0x00641823; // subu v1,v1,a0
820+ g_object[g_objpos++]=0x04420001; // bltzl v0,negative
821+ g_object[g_objpos++]=0x00031823; // subu v1,zero,v1
822+ // negative:
823+ g_object[g_objpos++]=0x04610003; // bgez v1,continue
824+ g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp)
825+ break_statement(); // (2 words)
826+ // continue:
827+ return 0;
828+}
829+
830+char* next_statement(){
831+ // Return to address stored in 4($sp)
832+ // while set $v0 to 8($sp) (see for_statement)
833+ // Following assembly must be 4 words.
834+ // If the number of words will be changed, link.c must be reviced for CONTINUE statement.
835+ check_obj_space(4);
836+ g_object[g_objpos++]=0x8FBF0004; // lw ra,4(sp)
837+ g_object[g_objpos++]=0x03E00008; // jr ra
838+ g_object[g_objpos++]=0x8FA20008; // lw v0,8(sp) (STEP value)
839+ g_object[g_objpos++]=0x0830000C; // addiu sp,sp,12 (see linker)
840+ return 0;
841+}
842+
843+char* do_statement(){
844+ char* err;
845+ // Usage of stack:
846+ // 4(sp): Address to return to in "DO" statement.
847+ check_obj_space(3);
848+ g_object[g_objpos++]=0x04130001;// bgezall zero,label1:
849+ g_object[g_objpos++]=0x0822FFFC;// addiu sp,sp,-4 (see linker)
850+ // label1:
851+ g_object[g_objpos++]=0xAFBF0004;// sw ra,4(sp)
852+ if (nextCodeIs("WHILE ")) {
853+ // DO WHILE
854+ err=get_floatOrValue();
855+ if (err) return err;
856+ check_obj_space(2);
857+ g_object[g_objpos++]=0x14400003; // bne v0,zero,labe2
858+ g_object[g_objpos++]=0x00000000; // nop
859+ return break_statement(); // (2 words)
860+ // label2:
861+
862+ } else if (nextCodeIs("UNTIL ")) {
863+ // DO UNTIL
864+ err=get_floatOrValue();
865+ if (err) return err;
866+ check_obj_space(2);
867+ g_object[g_objpos++]=0x10400003; // beq v0,zero,label2
868+ g_object[g_objpos++]=0x00000000; // nop
869+ return break_statement(); // (2 words)
870+ // label2:
871+ } else {
872+ // DO statement without WHILE/UNTIL
873+ return 0;
874+ }
875+}
876+
877+char* loop_statement(){
878+ char* err;
879+ int opos;
880+ opos=g_objpos;
881+ if (nextCodeIs("WHILE ")) {
882+ // LOOP WHILE
883+ err=get_floatOrValue();
884+ if (err) return err;
885+ check_obj_space(1);
886+ g_object[g_objpos++]=0x10400003; // beq v0,zero,label1
887+ } else if (nextCodeIs("UNTIL ")) {
888+ // LOOP UNTIL
889+ err=get_floatOrValue();
890+ if (err) return err;
891+ check_obj_space(1);
892+ g_object[g_objpos++]=0x14400003; // bne v0,zero,label
893+ } else {
894+ // LOOP statement without WHILE/UNTIL
895+ }
896+ check_obj_space(4);
897+ g_object[g_objpos++]=0x8FBF0004; // lw ra,4(sp)
898+ g_object[g_objpos++]=0x03E00008; // jr ra
899+ opos=g_objpos+1-opos;
900+ g_object[g_objpos++]=0x3000F000|opos; // nop (See linker, used for CONTINUE statement)
901+ // label1:
902+ g_object[g_objpos++]=0x08320004; // addiu sp,sp,4 (See link() function)
903+ return 0;
904+}
905+
906+char* while_statement(){
907+ char* err;
908+ check_obj_space(3);
909+ g_object[g_objpos++]=0x04130001; // bgezall zero,label1:
910+ g_object[g_objpos++]=0x0821FFFC; // addiu sp,sp,-4 (see linker)
911+ // label1:
912+ g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp)
913+ err=get_floatOrValue();
914+ if (err) return err;
915+ check_obj_space(2);
916+ g_object[g_objpos++]=0x14400003; // bne v0,zero,label2
917+ g_object[g_objpos++]=0x00000000; // nop
918+ return break_statement(); // (2 words)
919+ // label2:
920+}
921+
922+char* wend_statement(){
923+ check_obj_space(4);
924+ g_object[g_objpos++]=0x8FBF0004; // lw ra,4(sp)
925+ g_object[g_objpos++]=0x03E00008; // jr ra
926+ g_object[g_objpos++]=0x3000F003; // nop (See linker, used for CONTINUE statement)
927+ // label1:
928+ g_object[g_objpos++]=0x08310004; // addiu sp,sp,4 (See link() function)
929+ return 0;
930+}
931+
932+char* param4_statement(enum libs lib){
933+ // lib is either LIB_PALETTE or LIB_GPALETTE
934+ // PALETTE N,R,G,B
935+ char* err;
936+ // Get N
937+ err=get_value();
938+ if (err) return err;
939+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
940+ g_srcpos++;
941+ check_obj_space(2);
942+ g_object[g_objpos++]=0x27BDFFF4; // addiu sp,sp,-12
943+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
944+ // Get R
945+ err=get_value();
946+ if (err) return err;
947+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
948+ g_srcpos++;
949+ check_obj_space(1);
950+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
951+ // Get G
952+ err=get_value();
953+ if (err) return err;
954+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
955+ g_srcpos++;
956+ check_obj_space(1);
957+ g_object[g_objpos++]=0xAFA2000C; // sw v0,12(sp)
958+ // Get B
959+ err=get_value();
960+ if (err) return err;
961+ call_lib_code(lib);
962+ check_obj_space(1);
963+ g_object[g_objpos++]=0x27BD000C; // addiu sp,sp,12
964+ return 0;
965+}
966+
967+char* param3_statement(enum libs lib){
968+ char* err;
969+ // Get 1st parameter
970+ err=get_value();
971+ if (err) return err;
972+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
973+ g_srcpos++;
974+ check_obj_space(2);
975+ g_object[g_objpos++]=0x27BDFFF8; // addiu sp,sp,-8
976+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
977+ // Get 2nd parameter
978+ err=get_value();
979+ if (err) return err;
980+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
981+ g_srcpos++;
982+ check_obj_space(1);
983+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
984+ // Get 3rd parameter
985+ err=get_value();
986+ if (err) return err;
987+ call_lib_code(lib);
988+ check_obj_space(1);
989+ g_object[g_objpos++]=0x27BD0008; // addiu sp,sp,8
990+ return 0;
991+}
992+
993+char* bgcolor_statement(){
994+ // BGCOLOR R,G,B
995+ return param3_statement(LIB_BGCOLOR);
996+}
997+
998+char* pcg_statement(){
999+ // PCG ASCII,D1,D2
1000+ return param3_statement(LIB_PCG);
1001+}
1002+
1003+char* usepcg_statement(){
1004+ int objpos=g_objpos;
1005+ if (get_value()) {
1006+ // Getting integer failed.
1007+ // It supporsed to be not parameter
1008+ // and same as parameter=1.
1009+ g_objpos=objpos;
1010+ check_obj_space(1);
1011+ g_object[g_objpos++]=0x34020001; //ori v0,zero,0x01
1012+ }
1013+ call_lib_code(LIB_USEPCG);
1014+ return 0;
1015+}
1016+
1017+char* usegraphic_statement(){
1018+ int objpos=g_objpos;
1019+ if (get_value()) {
1020+ // Getting integer failed.
1021+ // It supporsed to be not parameter
1022+ // and same as parameter=1.
1023+ g_objpos=objpos;
1024+ check_obj_space(1);
1025+ g_object[g_objpos++]=0x34020001; //ori v0,zero,0x01
1026+ }
1027+ call_lib_code(LIB_USEGRAPHIC);
1028+ return 0;
1029+}
1030+
1031+char* cls_statement(){
1032+ call_lib_code(LIB_CLS);
1033+ return 0;
1034+}
1035+
1036+char* gcls_statement(){
1037+ call_lib_code(LIB_GCLS);
1038+ return 0;
1039+}
1040+
1041+char* color_statement(){
1042+ char* err;
1043+ err=get_value();
1044+ if (err) return err;
1045+ call_lib_code(LIB_COLOR);
1046+ return 0;
1047+}
1048+
1049+char* gcolor_statement(){
1050+ char* err;
1051+ err=get_value();
1052+ if (err) return err;
1053+ call_lib_code(LIB_GCOLOR);
1054+ return 0;
1055+}
1056+
1057+char* param2_statement(enum libs lib){
1058+ char* err;
1059+ // Get 1st
1060+ err=get_value();
1061+ if (err) return err;
1062+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1063+ g_srcpos++;
1064+ check_obj_space(2);
1065+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
1066+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
1067+ // Get 2nd
1068+ err=get_value();
1069+ if (err) return err;
1070+ call_lib_code(lib);
1071+ check_obj_space(1);
1072+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
1073+ return 0;
1074+}
1075+
1076+char* system_statement(){
1077+ // SYSTEM X,Y
1078+ char* err;
1079+ // Get 1st
1080+ err=get_value();
1081+ if (err) return err;
1082+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1083+ g_srcpos++;
1084+ check_obj_space(2);
1085+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
1086+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
1087+ // Get 2nd
1088+ err=get_value();
1089+ if (err) return err;
1090+ check_obj_space(2);
1091+ g_object[g_objpos++]=0x8FA40004; // lw a0,4(sp)
1092+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
1093+ call_lib_code(LIB_SYSTEM);
1094+ return 0;
1095+}
1096+
1097+char* cursor_statement(){
1098+ // CURSOR X,Y
1099+ return param2_statement(LIB_CURSOR);
1100+}
1101+
1102+char* scroll_statement(){
1103+ // SCROLL X,Y
1104+ return param2_statement(LIB_SCROLL);
1105+}
1106+
1107+char* drawcount_statement(){
1108+ char* err;
1109+ err=get_value();
1110+ if (err) return err;
1111+ call_lib_code(LIB_SETDRAWCOUNT);
1112+ return 0;
1113+}
1114+
1115+char* wait_statement(){
1116+ char* err;
1117+ err=get_value();
1118+ if (err) return err;
1119+ call_lib_code(LIB_WAIT);
1120+ return 0;
1121+}
1122+
1123+char* width_statement(){
1124+ char* err;
1125+ err=get_value();
1126+ if (err) return err;
1127+ call_lib_code(LIB_WIDTH);
1128+ return 0;
1129+}
1130+
1131+char* var_statement_sub(int a0, int a1){
1132+ // Construct parameter-setting scripts
1133+ if (a0&0xffff0000) {
1134+ check_obj_space(1);
1135+ g_object[g_objpos++]=0x3C040000|(a0>>16); // lui a0,XXXX
1136+ if (a0&0x0000ffff) {
1137+ check_obj_space(1);
1138+ g_object[g_objpos++]=0x34840000|(a0&0xffff); // ori a0,a0,XXXX
1139+ }
1140+ } else if (a0&0x0000ffff) {
1141+ check_obj_space(1);
1142+ g_object[g_objpos++]=0x34040000|(a0&0xffff); // ori a0,zero,xxxx
1143+ }
1144+ if (a1&0xffff0000) {
1145+ check_obj_space(1);
1146+ g_object[g_objpos++]=0x3C050000|(a1>>16); // lui a1,XXXX
1147+ if (a1&0x0000ffff) {
1148+ check_obj_space(1);
1149+ g_object[g_objpos++]=0x34A50000|(a1&0xffff); // ori a1,a1,XXXX
1150+ }
1151+ } else if (a1&0x0000ffff) {
1152+ check_obj_space(1);
1153+ g_object[g_objpos++]=0x34050000|(a1&0xffff); // ori a1,zero,xxxx
1154+ } else if (a0&0xff000000) {
1155+ // # of variables is 4. Reset $a1 to let lib_var() know that there is no more variables to store.
1156+ check_obj_space(1);
1157+ g_object[g_objpos++]=0x34050000; // ori a1,zero,0
1158+ }
1159+ return 0;
1160+}
1161+
1162+char* var_statement(){
1163+ char* err;
1164+ int i,j,a0,a1;
1165+ static int prevpos;
1166+ short stack;
1167+ do {
1168+ // For stack, 4 bytes are used for return address,
1169+ // 4 bytes are used in lib_var(),
1170+ // and additinal bytes are used for storing variable values.
1171+ stack=8;
1172+ a0=a1=0;
1173+ for (i=0;i<8;i++){
1174+ // Determine the variable number from source code
1175+ j=get_var_number();
1176+ if (j<0) return ERR_SYNTAX;
1177+ stack+=4;
1178+ // Create parameters in $a0, or $a1
1179+ if (i<4) {
1180+ a0=(a0<<8)|(j+1);
1181+ } else {
1182+ a1=(a1<<8)|(j+1);
1183+ }
1184+ // Check remaining variable(s)
1185+ if (g_source[g_srcpos]=='#' || g_source[g_srcpos]=='$') g_srcpos++;
1186+ next_position();
1187+ if (g_source[g_srcpos]!=',') break;
1188+ g_srcpos++;
1189+ }
1190+ // Jump to push routine, first
1191+ check_obj_space(2);
1192+ prevpos=g_objpos;
1193+ g_object[g_objpos++]=0x04130000; // bgezall zero,label1
1194+ g_object[g_objpos++]=0x27BD0000|((0-stack)&0xffff); // addiu sp,sp,-xx
1195+ // Process will be here after RETURN statement
1196+ // Pop routine
1197+ err=var_statement_sub(a0,a1); // Prepare a0, and a1
1198+ if (err) return err;
1199+ call_lib_code(LIB_VAR_POP);
1200+ // Restore stack and return
1201+ check_obj_space(3);
1202+ g_object[g_objpos++]=0x8FA30000|stack; // lw v1,xx(sp)
1203+ g_object[g_objpos++]=0x00600008; // jr v1
1204+ g_object[g_objpos++]=0x27BD0000|stack; // addiu sp,sp,xx
1205+ // Push rotine
1206+ g_object[prevpos]|=g_objpos-prevpos-1; // label1:
1207+ check_obj_space(1);
1208+ g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp)
1209+ err=var_statement_sub(a0,a1); // Prepare a0, and a1
1210+ if (err) return err;
1211+ call_lib_code(LIB_VAR_PUSH);
1212+
1213+ } while (g_source[g_srcpos-1]==',');
1214+ return 0;
1215+}
1216+
1217+
1218+char* graphic_statement(enum functions func){
1219+ /*
1220+ PSET X1,Y1[,C]
1221+ LINE X1,Y1,X2,Y2[,C]
1222+ BOXFILL X1,Y1,X2,Y2[,C]
1223+ CIRCLE X1,Y1,R[,C]
1224+ CIRCLEFILL X1,Y1,R[,C]
1225+ GPRINT X1,Y1,C,BC,S$
1226+ PUTBMP X1,Y1,M,N,BMP
1227+ 4(sp): X1
1228+ 8(sp): Y1
1229+ 12(sp): X2/R/M
1230+ 16(sp): Y2/N
1231+ v0: C/S$/BMP
1232+ */
1233+ char* err;
1234+ int paramnum;
1235+ switch(func){
1236+ case FUNC_PSET:// X1,Y1[,C]
1237+ case FUNC_GCOLOR:// X1,Y1
1238+ case FUNC_POINT:// X1,Y1
1239+ paramnum=2;
1240+ break;
1241+ case FUNC_CIRCLE:// X1,Y1,R[,C]
1242+ case FUNC_CIRCLEFILL:// X1,Y1,R[,C]
1243+ paramnum=3;
1244+ break;
1245+ case FUNC_LINE:// X1,Y1,X2,Y2[,C]
1246+ case FUNC_BOXFILL:// X1,Y1,X2,Y2[,C]
1247+ paramnum=4;
1248+ break;
1249+ case FUNC_GPRINT:// X1,Y1,C,BC,S$
1250+ case FUNC_PUTBMP:// X1,Y1,M,N,BMP
1251+ paramnum=5;
1252+ break;
1253+ default:
1254+ return ERR_UNKNOWN;
1255+ }
1256+
1257+ next_position();
1258+ if (g_source[g_srcpos]==',') {
1259+ // X1 and Y1 is omitted. Set 0x80000000 for both.
1260+ check_obj_space(4);
1261+ g_object[g_objpos++]=0x27BDFFF0; // addiu sp,sp,-16
1262+ g_object[g_objpos++]=0x3C028000; // lui v0,0x0080
1263+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
1264+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
1265+ } else {
1266+ // X1
1267+ err=get_value();
1268+ if (err) return err;
1269+ check_obj_space(2);
1270+ g_object[g_objpos++]=0x27BDFFF0; // addiu sp,sp,-16
1271+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
1272+ // Y1
1273+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1274+ g_srcpos++;
1275+ err=get_value();
1276+ if (err) return err;
1277+ check_obj_space(1);
1278+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
1279+ }
1280+ if (2<paramnum) {
1281+ // X2, R, or M
1282+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1283+ g_srcpos++;
1284+ err=get_value();
1285+ if (err) return err;
1286+ check_obj_space(1);
1287+ g_object[g_objpos++]=0xAFA2000C; // sw v0,12(sp)
1288+ if (3<paramnum) {
1289+ // Y2, BC, or N
1290+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1291+ g_srcpos++;
1292+ err=get_value();
1293+ if (err) return err;
1294+ check_obj_space(1);
1295+ g_object[g_objpos++]=0xAFA20010; // sw v0,16(sp)
1296+ }
1297+ }
1298+ if (func==FUNC_GPRINT) {
1299+ // S$
1300+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1301+ g_srcpos++;
1302+ err=get_string();
1303+ if (err) return err;
1304+ } else if (func==FUNC_PUTBMP) {
1305+ // BMP
1306+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1307+ g_srcpos++;
1308+ err=get_label();
1309+ if (g_label && !err) {
1310+ // Label/number is constant.
1311+ // Linker will change following codes later.
1312+ // Note that 0x0814xxxx and 0x0815xxxx are specific codes for these.
1313+ check_obj_space(2);
1314+ g_object[g_objpos++]=0x08140000|((g_label>>16)&0x0000FFFF); // lui v0,xxxx
1315+ g_object[g_objpos++]=0x08150000|(g_label&0x0000FFFF); // ori v0,v0,xxxx
1316+ // Change func to FUNC_PUTBMP2 (label mode).
1317+ func=FUNC_PUTBMP2;
1318+ } else {
1319+ err=get_value();
1320+ if (err) return err;
1321+ }
1322+ } else {
1323+ // [,C]
1324+ if (g_source[g_srcpos]==',') {
1325+ g_srcpos++;
1326+ err=get_value();
1327+ if (err) return err;
1328+ } else {
1329+ // If C is omitted, use -1.
1330+ check_obj_space(1);
1331+ g_object[g_objpos++]=0x2402FFFF; // addiu v0,zero,-1
1332+ }
1333+ }
1334+ // Call library
1335+ call_lib_code(LIB_GRAPHIC | func);
1336+ // Restore stack pointer
1337+ check_obj_space(1);
1338+ g_object[g_objpos++]=0x27BD0010; // addiu sp,sp,16
1339+ return 0;
1340+}
1341+
1342+char* fopen_statement_main(enum functions func){
1343+ // func is either FUNC_FOPENST or FUNC_FOPEN
1344+ char* err;
1345+ // Get 1st
1346+ err=get_string();
1347+ if (err) return err;
1348+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1349+ g_srcpos++;
1350+ check_obj_space(2);
1351+ g_object[g_objpos++]=0x27BDFFF8; // addiu sp,sp,-8
1352+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
1353+ // Get 2nd
1354+ err=get_string();
1355+ if (err) return err;
1356+ check_obj_space(1);
1357+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
1358+ // Get 3rd
1359+ if (g_source[g_srcpos]==',') {
1360+ g_srcpos++;
1361+ err=get_value();
1362+ if (err) return err;
1363+ } else {
1364+ // If 3rd parameter is omitted, use 0.
1365+ check_obj_space(1);
1366+ g_object[g_objpos++]=0x24020000; // addiu v0,zero,0
1367+ }
1368+ call_lib_code(LIB_FILE | func);
1369+ check_obj_space(1);
1370+ g_object[g_objpos++]=0x27BD0008; // addiu sp,sp,8
1371+ return 0;
1372+}
1373+
1374+char* file_statement(){
1375+ char* err;
1376+ err=get_value();
1377+ if (err) return err;
1378+ call_lib_code(LIB_FILE | FUNC_FILE);
1379+ return 0;
1380+}
1381+
1382+char* fclose_statement(){
1383+ char* err;
1384+ int orgpos=g_srcpos;
1385+ if (endOfStatement()) {
1386+ // If no argument, use 0
1387+ check_obj_space(1);
1388+ g_object[g_objpos++]=0x24020000; // addiu v0,zero,0
1389+ } else {
1390+ err=get_value();
1391+ if (err) return err;
1392+ }
1393+ call_lib_code(LIB_FILE | FUNC_FCLOSE);
1394+ return 0;
1395+}
1396+
1397+char* fget_statement(){
1398+ return param2_statement(LIB_FILE | FUNC_FGET);
1399+}
1400+
1401+char* fput_statement(){
1402+ return param2_statement(LIB_FILE | FUNC_FPUT);
1403+}
1404+
1405+char* fseek_statement(){
1406+ char* err;
1407+ err=get_value();
1408+ if (err) return err;
1409+ call_lib_code(LIB_FILE | FUNC_FSEEK);
1410+ return 0;
1411+}
1412+
1413+char* fputc_statement(){
1414+ char* err;
1415+ err=get_value();
1416+ if (err) return err;
1417+ call_lib_code(LIB_FILE | FUNC_FPUTC);
1418+ return 0;
1419+}
1420+
1421+char* fremove_statement(){
1422+ char* err;
1423+ err=get_string();
1424+ if (err) return err;
1425+ call_lib_code(LIB_FILE | FUNC_FREMOVE);
1426+ return 0;
1427+}
1428+
1429+char* usevar_statement(){
1430+ char* err;
1431+ int i;
1432+ do {
1433+ next_position();
1434+ i=check_var_name();
1435+ if (i<65536) return ERR_SYNTAX;
1436+ err=register_var_name(i);
1437+ if (err) return err;
1438+ if (g_source[g_srcpos]=='#' || g_source[g_srcpos]=='$') g_srcpos++;
1439+ next_position();
1440+ if (g_source[g_srcpos]==',') {
1441+ g_srcpos++;
1442+ } else {
1443+ break;
1444+ }
1445+ } while(1);
1446+ return 0;
1447+}
1448+
1449+char* playwave_statement(){
1450+ char* err;
1451+ err=get_string();
1452+ if (err) return err;
1453+ check_obj_space(2);
1454+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
1455+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
1456+ if (g_source[g_srcpos]==',') {
1457+ g_srcpos++;
1458+ // Get 2nd
1459+ err=get_value();
1460+ if (err) return err;
1461+ } else {
1462+ // If 2rd parameter is omitted, use 0.
1463+ check_obj_space(1);
1464+ g_object[g_objpos++]=0x24020000; // addiu v0,zero,0
1465+ }
1466+ call_lib_code(LIB_PLAYWAVE);
1467+ check_obj_space(1);
1468+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
1469+ return 0;
1470+}
1471+
1472+#ifdef __DEBUG
1473+ char* debug_statement(){
1474+ call_lib_code(LIB_DEBUG);
1475+ return 0;
1476+ }
1477+#endif
1478+
1479+// Aliases follow
1480+
1481+char* palette_statement(){
1482+ return param4_statement(LIB_PALETTE);
1483+}
1484+
1485+char* gpalette_statement(){
1486+ return param4_statement(LIB_GPALETTE);
1487+}
1488+
1489+char* print_statement(){
1490+ return print_statement_main(LIB_PRINTSTR,LIB_STRING);
1491+}
1492+
1493+char* pset_statement(){
1494+ return graphic_statement(FUNC_PSET);
1495+}
1496+
1497+char* line_statement(){
1498+ return graphic_statement(FUNC_LINE);
1499+}
1500+
1501+char* boxfill_statement(){
1502+ return graphic_statement(FUNC_BOXFILL);
1503+}
1504+
1505+char* circle_statement(){
1506+ return graphic_statement(FUNC_CIRCLE);
1507+}
1508+
1509+char* circlefill_statement(){
1510+ return graphic_statement(FUNC_CIRCLEFILL);
1511+}
1512+
1513+char* gprint_statement(){
1514+ return graphic_statement(FUNC_GPRINT);
1515+}
1516+
1517+char* putbmp_statement(){
1518+ return graphic_statement(FUNC_PUTBMP);
1519+}
1520+
1521+char* point_statement(){
1522+ return graphic_statement(FUNC_POINT);
1523+}
1524+
1525+char* fopen_statement(){
1526+ return fopen_statement_main(FUNC_FOPENST);
1527+}
1528+
1529+char* fprint_statement(){
1530+ return print_statement_main(LIB_FILE | FUNC_FPRINTSTR,LIB_FILE | FUNC_FSTRING);
1531+}
1532+
1533+static const void* statement_list[]={
1534+ "REM",rem_statement,
1535+ "SOUND ",sound_statement,
1536+ "MUSIC ",music_statement,
1537+ "DRAWCOUNT ",drawcount_statement,
1538+ "CURSOR ",cursor_statement,
1539+ "PALETTE ",palette_statement,
1540+ "GPALETTE ",gpalette_statement,
1541+ "BGCOLOR ",bgcolor_statement,
1542+ "CLS",cls_statement,
1543+ "GCLS",gcls_statement,
1544+ "COLOR ",color_statement,
1545+ "GCOLOR ",gcolor_statement,
1546+ "RESTORE ",restore_statement,
1547+ "DATA ",data_statement,
1548+ "CDATA ",cdata_statement,
1549+ "LABEL ",label_statement,
1550+ "DIM ",dim_statement,
1551+ "CLEAR",clear_statement,
1552+ "PRINT",print_statement,
1553+ "IF ",if_statement,
1554+ "ELSEIF ",elseif_statement,
1555+ "ELSE",else_statement,
1556+ "ENDIF",endif_statement,
1557+ "END",end_statement,
1558+ "EXEC ",exec_statement,
1559+ "GOTO ",goto_statement,
1560+ "GOSUB ",gosub_statement,
1561+ "RETURN",return_statement,
1562+ "POKE ",poke_statement,
1563+ "FOR ",for_statement,
1564+ "NEXT",next_statement,
1565+ "LET ",let_statement,
1566+ "PCG ",pcg_statement,
1567+ "USEPCG",usepcg_statement,
1568+ "SCROLL ",scroll_statement,
1569+ "WAIT ",wait_statement,
1570+ "USEGRAPHIC",usegraphic_statement,
1571+ "PSET ",pset_statement,
1572+ "LINE ",line_statement,
1573+ "BOXFILL ",boxfill_statement,
1574+ "CIRCLE ",circle_statement,
1575+ "CIRCLEFILL ",circlefill_statement,
1576+ "GPRINT ",gprint_statement,
1577+ "PUTBMP ",putbmp_statement,
1578+ "POINT ",point_statement,
1579+ "VAR ",var_statement,
1580+ "DO",do_statement,
1581+ "LOOP",loop_statement,
1582+ "WHILE ",while_statement,
1583+ "WEND",wend_statement,
1584+ "BREAK",break_statement,
1585+ "CONTINUE",continue_statement,
1586+ "SYSTEM",system_statement,
1587+ "WIDTH ",width_statement,
1588+ "FOPEN ",fopen_statement,
1589+ "FILE ",file_statement,
1590+ "FCLOSE",fclose_statement,
1591+ "FPRINT ",fprint_statement,
1592+ "FGET ",fget_statement,
1593+ "FPUT ",fput_statement,
1594+ "FPUTC ",fputc_statement,
1595+ "FSEEK ",fseek_statement,
1596+ "FREMOVE ",fremove_statement,
1597+ "USEVAR ",usevar_statement,
1598+ "PLAYWAVE ",playwave_statement,
1599+ // List of additional statements follows
1600+ ADDITIONAL_STATEMENTS
1601+};
1602+
1603+char* statement(void){
1604+ char* err;
1605+ int prevpos;
1606+ int i;
1607+ char* (*f)();
1608+ // Clear flag for temp area usage.
1609+ g_temp_area_used=0;
1610+ // Initialize stack handler used for value
1611+ g_sdepth=g_maxsdepth=0;
1612+ // Seek the statement
1613+ for (i=0;i<sizeof(statement_list)/sizeof(statement_list[0]);i+=2){
1614+ if (nextCodeIs((char*)statement_list[i])) break;
1615+ }
1616+ if (i<sizeof(statement_list)/sizeof(statement_list[0])) {
1617+ // Statement found. Call it.
1618+ f=statement_list[i+1];
1619+ err=f();
1620+#ifdef __DEBUG
1621+ } else if (nextCodeIs("DEBUG")) {
1622+ err=debug_statement();
1623+#endif
1624+ } else {
1625+ err=let_statement();
1626+ }
1627+ if (err) return err;
1628+ // Stack handler must be zero here.
1629+ if (g_sdepth!=0) return ERR_UNKNOWN;
1630+ // Check if temp area is used
1631+ if (g_temp_area_used) {
1632+ // Temp area is used. Insert a garbage collection flag setting routine.
1633+ check_obj_space(1);
1634+ g_object[g_objpos++]=0x7ED6F000;// ext s6,s6,0,31
1635+ }
1636+ return 0;
1637+}
--- mips/trunk/megalopa/error.c (nonexistent)
+++ mips/trunk/megalopa/error.c (revision 268)
@@ -0,0 +1,170 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by Katsumi.
4+ http://hp.vector.co.jp/authors/VA016157/
5+ kmorimatsu@users.sourceforge.jp
6+*/
7+
8+#include "compiler.h"
9+
10+const char* g_err_str[]={
11+ "Syntax error",
12+ "Not enough binary space",
13+ "Not enough memory",
14+ "Divided by zero",
15+ "Not yet implemented",
16+ "Label or line number not found: ",
17+ "Label too long or too short",
18+ "String too complexed",
19+ "Data not found",
20+ "Unknown error:",
21+ "Music syntax error:'",
22+ " found more than twice",
23+ "Break",
24+ "Unexpected NEXT or RETURN statement",
25+ "Cannot assign temporary block",
26+ "GOSUB fuction cannot be used after string-handling",
27+ "Invalid BREAK statement in line ",
28+ "Invalid ELSE/IF statement in line ",
29+ "Invalid parameter(s)",
30+ "File error",
31+ "Invalid variable name",
32+ "WAVE format error",
33+};
34+
35+char* resolve_label(int s6){
36+ static char str[7];
37+ int i,j;
38+ if (s6<65536) {
39+ // Line number
40+ for(i=0;i<5;i++){
41+ str[5-i]='0'+rem10_32(s6);
42+ s6=div10_32(s6);
43+ }
44+ str[6]=0x00;
45+ for(j=1;j<5;j++){
46+ if (str[j]!='0') break;
47+ }
48+ return (char*)(str+j);
49+ } else {
50+ // Label
51+ s6-=65536;
52+ str[6]=0x00;
53+ for(i=5;0<=i;i--){
54+ if (s6<36) {
55+ // First character must be A-Z, corresponding to 1-26 but not 10-35.
56+ // See get_label() for the detail.
57+ str[i]=s6-1+'A';
58+ break;
59+ } else {
60+ // From second, 0-9 corresponds to 0-9 and A-Z corresponds to 10-35.
61+ str[i]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[rem36_32(s6)];
62+ s6=div36_32(s6);
63+ }
64+ }
65+ return (char*)(str+i);
66+ }
67+}
68+
69+void pre_end_addr(int s6){
70+ int i,j;
71+ char str[7];
72+ // Cool down the system
73+ stop_music();
74+ // Resolve line and show it
75+ if (s6<0) s6=s6&0x7fffffff;
76+ g_label=s6;
77+ if (s6<65536) {
78+ // Line number
79+ printstr("\nIn line ");
80+ } else {
81+ // Label
82+ printstr("\nAfter label ");
83+ }
84+ printstr(resolve_label(s6));
85+ asm volatile("la $v0,%0"::"i"(&g_end_addr));
86+ asm volatile("lw $v0,0($v0)");
87+ asm volatile("nop");
88+ asm volatile("jr $v0");
89+}
90+
91+#define end_exec() \
92+ asm volatile("addu $a0,$s6,$zero");\
93+ asm volatile("j pre_end_addr")
94+
95+void err_break(void){
96+ stop_music();
97+ printstr(ERR_BREAK);
98+ end_exec();
99+}
100+
101+void err_data_not_found(void){
102+ printstr(ERR_DATA_NF);
103+ end_exec();
104+}
105+
106+void err_label_not_found(void){
107+ printstr(ERR_LABEL_NF);
108+ printstr(resolve_label(g_label));
109+ printstr("\n");
110+ end_exec();
111+}
112+
113+void err_div_zero(void){
114+ printstr(ERR_DIV_0);
115+ end_exec();
116+}
117+
118+void err_no_mem(void){
119+ printstr(ERR_NE_MEMORY);
120+ end_exec();
121+}
122+
123+void err_str_complex(void){
124+ printstr(ERR_STR_COMPLEX);
125+ end_exec();
126+}
127+
128+void err_unknown(void){
129+ asm volatile("la $v0,%0"::"i"(&g_temp));
130+ asm volatile("sw $ra,0($v0)");
131+ printstr(ERR_UNKNOWN);
132+ printhex32(g_temp);
133+ end_exec();
134+}
135+
136+void err_music(char* str){
137+ printstr(ERR_MUSIC);
138+ printstr(str);
139+ printstr("'\n");
140+ // Restore s6 from g_s6
141+ asm volatile("la $s6,%0"::"i"(&g_s6));
142+ asm volatile("lw $s6,0($s6)");
143+ end_exec();
144+}
145+
146+void err_unexp_next(void){
147+ printstr(ERR_UNEXP_NEXT);
148+ end_exec();
149+}
150+
151+void err_no_block(void){
152+ printstr(ERR_NO_BLOCK);
153+ end_exec();
154+}
155+
156+void err_invalid_param(void){
157+ printstr(ERR_INVALID_PARAM);
158+ end_exec();
159+}
160+
161+void err_file(void){
162+ printstr(ERR_FILE);
163+ end_exec();
164+}
165+
166+void err_wave(void){
167+ printstr(ERR_WAVE);
168+ end_exec();
169+}
170+
--- mips/trunk/megalopa/debug.h (nonexistent)
+++ mips/trunk/megalopa/debug.h (revision 268)
@@ -0,0 +1,30 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by K.Tanaka & Katsumi
4+ http://www.ze.em-net.ne.jp/~kenken/index.html
5+ http://hp.vector.co.jp/authors/VA016157/
6+*/
7+
8+#ifdef __DEBUG
9+
10+// Pseudo reading config setting for debug mode
11+extern unsigned int g_DEVCFG1;
12+#define DEVCFG1 g_DEVCFG1
13+
14+// Do not use PS/2 keyboard
15+#define ps2init() not_ps2init_but_init_Timer1()
16+int not_ps2init_but_init_Timer1();
17+
18+// Do not use asm("wait") but use asm("nop")
19+#undef WAIT
20+#define WAIT "nop"
21+
22+#endif // __DEBUG
23+
24+// key waiting macro
25+
26+#define debug_wait() lineinput((char*)&g_temp,3)
27+#define debug_wait_char(x) do {\
28+ printchar(x); \
29+ lineinput((char*)&g_temp,3);\
30+ } while(0)
--- mips/trunk/megalopa/editor.c (nonexistent)
+++ mips/trunk/megalopa/editor.c (revision 268)
@@ -0,0 +1,2554 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by K.Tanaka
4+ http://www.ze.em-net.ne.jp/~kenken/index.html
5+*/
6+
7+#include <xc.h>
8+#include "api.h"
9+#include "editor.h"
10+#include "keyinput.h"
11+#include "compiler.h"
12+#include "main.h"
13+
14+struct _TBUF{
15+//リンク付きのテキストバッファ
16+ struct _TBUF *prev;//前方へのリンク。NULLの場合先頭または空き
17+ struct _TBUF *next;//後方へのリンク。NULLの場合最後
18+ unsigned short n;//現在の使用バイト数
19+ unsigned char Buf[TBUFSIZE];//バッファ
20+} ;
21+typedef struct _TBUF _tbuf;
22+
23+//_tbuf TextBuffer[TBUFMAXLINE]; //テキストバッファ
24+_tbuf *TextBuffer; //実体は配列RAM[]の中に確保する
25+
26+_tbuf *TBufstart; //テキストバッファの先頭位置
27+_tbuf *cursorbp; //現在のカーソル位置のテキストバッファ
28+unsigned short cursorix; //現在のカーソル位置のテキストバッファ先頭からの位置
29+_tbuf *disptopbp; //現在表示中画面左上のテキストバッファ
30+unsigned short disptopix; //現在表示中画面左上のテキストバッファ先頭からの位置
31+int num; //現在バッファ内に格納されている文字数
32+int cx,cy; //カーソル座標
33+int cx2; //上下移動時の仮カーソルX座標
34+_tbuf *cursorbp1; //範囲選択時のカーソルスタート位置のテキストバッファ、範囲選択モードでない場合NULL
35+unsigned short cursorix1; //範囲選択時のカーソルスタート位置のテキストバッファ先頭からの位置
36+int cx1,cy1; //範囲選択時のカーソルスタート座標
37+int line_no; //現在のカーソル位置の行
38+int line_no1; //範囲選択時のカーソルスタート位置の行
39+
40+// カーソル関連位置の一時避難用
41+_tbuf *cursorbp_t;
42+unsigned short cursorix_t;
43+_tbuf *disptopbp_t;
44+unsigned short disptopix_t;
45+int cx_t,cy_t,line_no_t;
46+
47+//unsigned char clipboard[WIDTH_XMAX*EDITWIDTHY]; //クリップボード、最大サイズは編集画面領域と同じ
48+unsigned char *clipboard; //実体は配列RAM[]の中に確保する
49+
50+int clipsize; //現在クリップボードに格納されている文字数
51+int edited; //保存後に変更されたかを表すフラグ
52+
53+//配列RAM[]内にメモリ動的確保するためのポインタ
54+char *editormallocp;
55+
56+//unsigned char filebuf[FILEBUFSIZE]; //ファイルアクセス用バッファ
57+unsigned char *filebuf; //実体は配列RAM[]の中に確保する
58+
59+//unsigned char cwdpath[PATHNAMEMAX]; //現在のディレクトリのパス名
60+unsigned char *cwdpath; //実体は配列RAM[]の中に確保する
61+
62+unsigned char currentfile[13],tempfile[13]; //編集中のファイル名、一時ファイル名
63+
64+//unsigned char filenames[MAXFILENUM][13]; //ロード時のファイル名一覧バッファ
65+unsigned char (*filenames)[13]; //実体は配列RAM[]の中に確保する
66+
67+//unsigned char undobuf[UNDOBUFSIZE]; //アンドゥ用バッファ
68+unsigned char *undobuf; //実体は配列RAM[]の中に確保する
69+unsigned char *undobuf_top; //アンドゥ用バッファの先頭を指すポインタ
70+int undobuf_used; //アンドゥ用バッファ使用量
71+
72+const unsigned char Message1[]="Hit Any Key\n";
73+const unsigned char Message2[]="File System Error\n";
74+const unsigned char Message3[]="Retry:[Enter] / Quit:[ESC]\n";
75+const unsigned char ROOTDIR[]="\\";
76+
77+unsigned char * editormalloc(int size){
78+//配列RAM[]内にサイズsizeの領域を確保し、先頭アドレスを返す
79+//確保できない場合は、エラー表示し動作停止
80+ unsigned char *p;
81+ if(editormallocp+size>RAM+RAMSIZE){
82+ printstr("Cannot allocate memory");
83+ while(1) asm("wait");
84+ }
85+ p=editormallocp;
86+ editormallocp+=size;
87+ return p;
88+}
89+
90+void wait60thsec(unsigned short n){
91+#ifndef __DEBUG
92+ // 60分のn秒ウェイト(ビデオ画面の最下行信号出力終了まで待つ)
93+ n+=drawcount;
94+ while(drawcount!=n) asm(WAIT);
95+#else
96+ // DEBUGモードでは、待ち時間無し
97+ drawcount+=n;
98+#endif
99+}
100+
101+unsigned int bpixtopos(_tbuf *bp,unsigned int ix){
102+// テキストバッファ上の位置からテキスト全体の先頭から何文字目かを返す
103+// bp:テキストバッファポインタ
104+// ix:bp->Bufの先頭からの文字数
105+ unsigned int pos;
106+ _tbuf *sbp;
107+ pos=0;
108+ sbp=TBufstart;
109+ while(sbp!=bp){
110+ pos+=sbp->n;
111+ sbp=sbp->next;
112+ if(sbp==NULL) return 0; //エラー
113+ }
114+ return pos+ix;
115+}
116+_tbuf * postobpix(int pos,unsigned short *pix){
117+// テキスト全体の先頭からpos文字目のテキストバッファ上の位置を返す
118+// 戻り値 テキストバッファポインタ
119+// *pix(戻り値):戻り値テキストバッファの先頭からの位置(ポインタ渡し)
120+ _tbuf *bp;
121+ bp=TBufstart;
122+ while(pos >= bp->n){
123+ if(bp->next==NULL) break; //全体最後尾の場合
124+ pos-=bp->n;
125+ bp=bp->next;
126+ }
127+ if(pos > bp->n){
128+ // オーバーランエラーの場合先頭を返す
129+ *pix=0;
130+ return TBufstart;
131+ }
132+ *pix=pos;
133+ return bp;
134+}
135+_tbuf * linetobpix(int line,unsigned short *pix){
136+// テキスト全体の先頭からline行目のテキストバッファ上の位置を返す
137+// 戻り値 テキストバッファポインタ
138+// *pix(戻り値):戻り値テキストバッファの先頭からの位置(ポインタ渡し)
139+ _tbuf *bp,*bp2;
140+ int ix,ix2;
141+ bp=TBufstart;
142+ bp2=TBufstart;
143+ ix=0;
144+ ix2=0;
145+ while(line>1){
146+ while(1){
147+ if(ix>=bp->n){
148+ if(bp->next==NULL) break;
149+ bp=bp->next;
150+ ix=0;
151+ continue;
152+ }
153+ if(bp->Buf[ix++] == '\n'){
154+ bp2=bp;
155+ ix2=ix;
156+ break;
157+ }
158+ }
159+ line--;
160+ }
161+ *pix=ix2;
162+ return bp2;
163+}
164+
165+_tbuf * newTBuf(_tbuf *prev){
166+// 新しいテキストバッファ1行を生成
167+// prev:挿入先の行(prevの後ろに追加)
168+// 戻り値 生成したバッファへのポインタ、生成できない場合NULL
169+ _tbuf *bp,*next;
170+
171+ //バッファの先頭から空きをサーチ
172+ bp=TextBuffer;
173+ while(1){
174+ if(bp->prev==NULL && bp!=TBufstart) break;
175+ bp++;
176+ if(bp>=TextBuffer+TBUFMAXLINE) return NULL;//最後まで空きなし
177+ }
178+ next=prev->next;
179+ //行挿入
180+ bp->prev=prev;
181+ bp->next=next;
182+ prev->next=bp;
183+ if(next!=NULL) next->prev=bp;
184+ bp->n=0;
185+ return bp;
186+}
187+
188+_tbuf * deleteTBuf(_tbuf *bp){
189+// テキストバッファの削除
190+// bp:削除する行のポインタ
191+// 戻り値 削除前の次のバッファへのポインタ、ない場合NULL
192+ unsigned short a,b;
193+ _tbuf *prev,*next;
194+ prev=bp->prev;
195+ next=bp->next;
196+ if(prev==NULL){
197+ //先頭行の場合
198+ if(next==NULL) return next; //最後の1行の場合は削除しない
199+ TBufstart=next; //次の行を先頭行設定
200+ }
201+ else prev->next=next; //前を次にリンク(最終行ならNULLがコピーされる)
202+ if(next!=NULL) next->prev=prev; //次があれば次を前にリンク
203+ bp->prev=NULL; //空きフラグ設定
204+ return next;
205+}
206+
207+// アンドゥバッファ
208+/*
209+UNDOBUFSIZEバイトの環状バッファ。テキストバッファに対する変更発生ごとに、
210+変更内容、変更場所をバッファの先頭に記録し、先頭位置を進める。
211+アンドゥ実行が呼び出されると、バッファ先頭から読み出し、テキストバッファに対して
212+元に戻す変更を行う。
213+バッファがいっぱいになると、最後尾から消去(上書き)していく。
214+
215+<バッファ仕様>
216+ 開始位置:テキストバッファトップから何バイト目か(2バイト。下位、上位の順)
217+ 繰り返し数:連続動作の場合の回数(2バイト。下位、上位の順)
218+ バッファの前からも後ろからも削除できるよう、先頭と最後に命令をおく。ただし、
219+ 後ろの命令コードが10以上の場合は削除された文字そのものを意味する。
220+1文字挿入
221+ UNDO_INSERT,開始位置,UNDO_INSERT
222+1文字上書き
223+ UNDO_OVERWRITE,開始位置,消去文字 [,消去文字が0?9の場合さらに0を付加]
224+1文字削除(Delete)
225+ UNDO_DELETE,開始位置,消去文字 [,消去文字が0?9の場合さらに0を付加]
226+1文字削除(BackSpace)
227+ UNDO_BACKSPACE,開始位置,消去文字 [,消去文字が0?9の場合さらに0を付加]
228+連続挿入(Ctrl+Vで貼り付け)
229+ UNDO_CONTINS,開始位置,繰り返し数,UNDO_CONTINS
230+連続削除(領域選択して削除)
231+ UNDO_CONTDEL,繰り返し数,消去文字列,開始位置,繰り返し数,UNDO_CONTDEL
232+*/
233+
234+void pushundomem(unsigned char c){
235+// アンドゥ用メモリの先頭に1バイトを貯める
236+// 空きがなくなった場合、最後尾の1命令分を無効化
237+ unsigned char *p;
238+ int n;
239+
240+ if(undobuf_used>=UNDOBUFSIZE){
241+ //空きがない場合、最後尾のブロックのバイト数分をバッファ利用済み量から減らす
242+ p=undobuf_top-undobuf_used; //最後尾
243+ if(p<undobuf) p+=UNDOBUFSIZE;
244+ switch(*p){
245+ case UNDO_INSERT: //1文字挿入
246+ undobuf_used-=4;
247+ break;
248+ case UNDO_OVERWRITE: //1文字上書き
249+ case UNDO_DELETE: //1文字削除
250+ case UNDO_BACKSPACE: //1文字削除(BS)
251+ undobuf_used-=4;
252+ p+=3;
253+ if(p>=undobuf+UNDOBUFSIZE) p-=UNDOBUFSIZE;
254+ if(*p<10) undobuf_used--; //コード0?9の場合後ろに0が付加されている
255+ break;
256+ case UNDO_CONTINS: //連続挿入
257+ undobuf_used-=6;
258+ break;
259+ case UNDO_CONTDEL: //連続削除
260+ //繰り返し数の読み出し
261+ p++;
262+ if(p>=undobuf+UNDOBUFSIZE) p-=UNDOBUFSIZE;
263+ n=*p++;
264+ if(p>=undobuf+UNDOBUFSIZE) p-=UNDOBUFSIZE;
265+ n+=*p<<8;
266+ undobuf_used-=n+8;
267+ break;
268+ }
269+ }
270+ //アンドゥバッファ先頭に1バイト挿入し、先頭位置を1進める
271+ *undobuf_top++=c;
272+ if(undobuf_top>=undobuf+UNDOBUFSIZE) undobuf_top-=UNDOBUFSIZE;
273+ undobuf_used++;
274+}
275+void pushundomem2(unsigned short w){
276+// アンドゥバッファに2バイト貯める、下位、上位の順
277+ pushundomem((unsigned char)w);
278+ pushundomem(w>>8);
279+}
280+unsigned char popundomem(){
281+// アンドゥバッファから1バイト読み出し、先頭を1つ戻す
282+// 戻り値:読み出したコード
283+ undobuf_top--;
284+ if(undobuf_top<undobuf) undobuf_top+=UNDOBUFSIZE;
285+ undobuf_used--;
286+ return *undobuf_top;
287+}
288+unsigned short popundomem2(){
289+// アンドゥバッファから2バイト読み出し
290+// 戻り値:読み出した2バイトコード
291+ unsigned short w;
292+ w=popundomem()<<8;
293+ w+=popundomem();
294+ return w;
295+}
296+void setundobuf(int com,_tbuf *bp,unsigned short ix,unsigned char c,unsigned short n){
297+//アンドゥバッファにデータをセットする
298+//com:コマンド 1:1文字削除、2:1文字上書き、3:1文字挿入、4:連続削除、5:連続挿入開始
299+//bp,ix:バッファ上の実行場所(カーソル位置)
300+//c:文字(上書き、挿入の場合のみ使用)
301+//n:連続数(連続の場合のみ使用)
302+ unsigned short pos;
303+
304+ pos=bpixtopos(bp,ix); //テキストバッファ先頭から何バイト目かを求める
305+ switch(com){
306+ case UNDO_INSERT: //1文字挿入
307+ pushundomem(com);
308+ pushundomem2(pos);
309+ pushundomem(com);
310+ break;
311+ case UNDO_OVERWRITE: //1文字上書き
312+ case UNDO_DELETE: //1文字削除(Delete)
313+ case UNDO_BACKSPACE: //1文字削除(BackSpace)
314+ pushundomem(com);
315+ pushundomem2(pos);
316+ pushundomem(c);
317+ if(c<10) pushundomem(0); //10未満のコードの場合0を付加
318+ break;
319+ case UNDO_CONTINS: //連続挿入
320+ pushundomem(com);
321+ pushundomem2(pos);
322+ pushundomem2(n);
323+ pushundomem(com);
324+ break;
325+ case UNDO_CONTDEL: //連続削除
326+ pushundomem(com);
327+ pushundomem2(n);
328+ break;
329+ }
330+}
331+
332+int insertchar(_tbuf *bp,unsigned int ix,unsigned char c,int undo){
333+//テキストバッファbpの先頭からixバイトの位置にcを挿入
334+//undo 0:通常(アンドゥバッファに格納する)、1:連続挿入中、2:アンドゥ中
335+//戻り値 成功:0、不正または容量オーバー:-1、空きがあるはずなのに失敗:1
336+ unsigned char *p;
337+
338+ if(ix > bp->n) return -1; //不正指定
339+ if(num >= TBUFMAXSIZE) return -1; //バッファ容量オーバー
340+ if(bp->n < TBUFSIZE){
341+ //ライン内だけで1バイト挿入可能//
342+ for(p=bp->Buf + bp->n ; p > bp->Buf+ix ; p--) *p=*(p-1);
343+ *p=c;
344+ if(!undo) setundobuf(UNDO_INSERT,bp,ix,0,0); //アンドゥバッファ設定
345+ bp->n++;
346+ num++; //バッファ使用量
347+// if(bp->n >= TBUFSIZE && bp->next==NULL) newTBuf(bp); //バッファがいっぱいになったら新たにバッファ生成
348+ return 0;
349+ }
350+ //ラインがあふれる場合
351+ if(bp->next==NULL || bp->next->n >=TBUFSIZE){
352+ // 最終行または次のラインバッファがいっぱいだったら一行挿入
353+ if(newTBuf(bp)==NULL){
354+ // ラインバッファ挿入不可
355+ return 1;
356+ }
357+ }
358+ if(ix==TBUFSIZE){
359+ insertchar(bp->next,0,c,undo);
360+ return 0;
361+ }
362+ p=bp->Buf + TBUFSIZE-1;
363+ insertchar(bp->next,0,*p,1); //次の行の先頭に1文字挿入(必ず空きあり)
364+ for( ; p > bp->Buf+ix ; p--) *p=*(p-1);
365+ *p=c;
366+ if(!undo) setundobuf(UNDO_INSERT,bp,ix,0,0); //アンドゥバッファ設定
367+ return 0;
368+}
369+
370+int overwritechar(_tbuf *bp,unsigned int ix,unsigned char c,int undo){
371+//テキストバッファbpの先頭からixバイトの位置をcで上書き
372+//undo 0:通常(アンドゥバッファに格納する)、1:連続中、2:アンドゥ中
373+//戻り値 成功:0、不正または容量オーバー:-1、空きがあるはずなのに失敗:1
374+
375+ //現在のバッファ位置の文字が終端または改行の場合、挿入モード
376+ if(ix > bp->n) return -1; //不正指定
377+ while(ix >= bp->n){
378+ if(bp->next==NULL){
379+ //テキスト全体最後尾の場合は挿入
380+ return insertchar(bp,ix,c,undo);
381+ }
382+ bp=bp->next;
383+ ix=0;
384+ }
385+ if(bp->Buf[ix]=='\n') return insertchar(bp,ix,c,undo);
386+ if(!undo) setundobuf(UNDO_OVERWRITE,bp,ix,bp->Buf[ix],0); //アンドゥバッファ設定
387+ bp->Buf[ix]=c;
388+ return 0;
389+}
390+
391+void deletechar(_tbuf *bp,unsigned int ix,int undo){
392+//テキストバッファbpの先頭からixバイトの位置の1バイト削除
393+//undo -1:通常BackSpace(アンドゥバッファに格納する)
394+// 0:通常DELETE(アンドゥバッファに格納する)、1:連続中、2:アンドゥ中
395+ unsigned char *p;
396+
397+ if(ix > bp->n) return; //不正指定
398+ if(ix !=bp->n){
399+ //バッファの最後の文字より後ろでない場合
400+
401+ //アンドゥバッファ設定
402+ if(undo==1) pushundomem(bp->Buf[ix]); //連続削除中
403+ else if(undo==-1) setundobuf(UNDO_BACKSPACE,bp,ix,bp->Buf[ix],0); //1文字削除(backspace)
404+ else if(undo==0) setundobuf(UNDO_DELETE,bp,ix,bp->Buf[ix],0); //1文字削除
405+
406+ for(p=bp->Buf+ix ; p< bp->Buf + bp->n-1 ; p++) *p=*(p+1);
407+ bp->n--;
408+ num--; //バッファ使用量
409+ return;
410+ }
411+ //行バッファの現在の最後の場合(削除する文字がない場合)
412+ if(bp->next==NULL) return; //全体の最後の場合、何もしない
413+ deletechar(bp->next,0,undo); //次の行の先頭文字を削除
414+}
415+int gabagecollect1(void){
416+//断片化されたテキストバッファの隙間を埋めるガベージコレクション
417+//カーソルの前と後ろそれぞれ探索して最初の1バイト分のみ実施
418+//戻り値 1バイトでも移動した場合:1、なかった場合:0
419+
420+ _tbuf *bp;
421+ int f=0;
422+ unsigned char *p,*p2;
423+
424+ //カーソルがバッファの先頭にある場合、前のバッファの最後尾に変更
425+ //(ただし前に空きがない場合と先頭バッファの場合を除く)
426+ while(cursorix==0 && cursorbp->prev!=NULL && cursorbp->prev->n <TBUFSIZE){
427+ cursorbp=cursorbp->prev;
428+ cursorix=cursorbp->n;
429+ }
430+ //画面左上位置がバッファの先頭にある場合、前のバッファの最後尾に変更
431+ //(ただし先頭バッファの場合を除く)
432+ while(disptopix==0 && disptopbp->prev!=NULL){
433+ disptopbp=disptopbp->prev;
434+ disptopix=disptopbp->n;
435+ }
436+ //カーソルのあるバッファ以外の空バッファを全て削除
437+ bp=TBufstart;
438+ while(bp!=NULL){
439+ if(bp->n == 0 && bp!=cursorbp){
440+ if(bp==disptopbp) disptopbp=bp->next; //画面左上位置が空バッファ先頭の場合、次にずらす
441+ bp=deleteTBuf(bp); //空きバッファ削除
442+ }
443+ else bp=bp->next;
444+ }
445+
446+ //カーソル位置より前の埋まっていないバッファを先頭からサーチ
447+ bp=TBufstart;
448+ while(bp->n >= TBUFSIZE){
449+ if(bp==cursorbp) break;
450+ bp=bp->next;
451+ }
452+ if(bp!=cursorbp){
453+ //最初に見つけた空き場所に次のバッファから1バイト移動
454+ bp->Buf[bp->n++] = bp->next->Buf[0];
455+ bp=bp->next;
456+ p=bp->Buf;
457+ p2=p+bp->n-1;
458+ for( ; p<p2 ; p++) *p=*(p+1);
459+ bp->n--;
460+ f=1;
461+ if(bp == disptopbp) disptopix--;
462+ if(bp == cursorbp) cursorix--;
463+// else if(bp->n == 0) deleteTBuf(bp);
464+ }
465+ if(cursorbp->next ==NULL) return f; //カーソル位置が最終バッファなら終了
466+ //カーソル位置の次のバッファから埋まっていないバッファをサーチ
467+ bp=cursorbp;
468+ do{
469+ bp=bp->next;
470+ if(bp->next ==NULL) return f; //最終バッファに到達なら終了
471+ } while(bp->n >=TBUFSIZE);
472+
473+ //最初に見つけた空き場所に次のバッファから1バイト移動
474+ bp->Buf[bp->n++] = bp->next->Buf[0];
475+ bp=bp->next;
476+ p=bp->Buf;
477+ p2=p+bp->n-1;
478+ for( ; p<p2 ; p++) *p=*(p+1);
479+ bp->n--;
480+ f=1;
481+ if(bp->n == 0) deleteTBuf(bp);
482+ return f;
483+}
484+void gabagecollect2(void){
485+// 変化がなくなるまで1バイト分のガベージコレクションを呼び出し
486+ while(gabagecollect1()) ;
487+}
488+void inittextbuf(void){
489+// テキストバッファの初期化
490+ _tbuf *bp;
491+ for(bp=TextBuffer;bp<TextBuffer+TBUFMAXLINE;bp++) bp->prev=NULL; //未使用バッファ化
492+ TBufstart=TextBuffer; //リンクの先頭設定
493+ TBufstart->next=NULL;
494+ TBufstart->n=0;
495+ num=0; //バッファ使用量
496+ edited=0; //編集済みフラグクリア
497+ undobuf_top=undobuf;
498+ undobuf_used=0;
499+}
500+void redraw(){
501+//画面の再描画
502+ unsigned char *vp;
503+ _tbuf *bp,*bp1,*bp2;
504+ int ix,ix1,ix2;
505+ int x,y;
506+ unsigned char ch,cl;
507+
508+ vp=TVRAM;
509+ bp=disptopbp;
510+ ix=disptopix;
511+ cl=COLOR_NORMALTEXT;
512+ if(cursorbp1==NULL){
513+ //範囲選択モードでない場合
514+ bp1=NULL;
515+ bp2=NULL;
516+ }
517+ else{
518+ //範囲選択モードの場合、開始位置と終了の前後判断して
519+ //bp1,ix1を開始位置、bp2,ix2を終了位置に設定
520+ if(cy<cy1 || (cy==cy1 && cx<cx1)){
521+ bp1=cursorbp;
522+ ix1=cursorix;
523+ bp2=cursorbp1;
524+ ix2=cursorix1;
525+ }
526+ else{
527+ bp1=cursorbp1;
528+ ix1=cursorix1;
529+ bp2=cursorbp;
530+ ix2=cursorix;
531+ }
532+ }
533+ for(y=0;y<EDITWIDTHY;y++){
534+ if(bp==NULL) break;
535+ for(x=0;x<twidth;x++){
536+ //文字がある位置までサーチ
537+ while(ix>=bp->n){
538+ if(bp==bp1 && ix==ix1){
539+ if(textmode!=TMODE_MONOTEXT){
540+ cl=COLOR_AREASELECTTEXT;
541+ }
542+ else{
543+ cl=COLOR_INV;
544+ }
545+ }
546+ if(bp==bp2 && ix==ix2) cl=COLOR_NORMALTEXT;
547+ bp=bp->next;
548+ ix=0;
549+ if(bp==NULL) break;
550+ }
551+ if(bp==NULL) break; //バッファ最終
552+ if(bp==bp1 && ix==ix1){
553+ if(textmode!=TMODE_MONOTEXT){
554+ cl=COLOR_AREASELECTTEXT;
555+ }
556+ else{
557+ cl=COLOR_INV;
558+ }
559+ }
560+ if(bp==bp2 && ix==ix2) cl=COLOR_NORMALTEXT;
561+ ch=bp->Buf[ix++];
562+ if(ch=='\n') break;
563+ *(vp+attroffset)=cl;
564+ *vp++=ch;
565+ }
566+ //改行およびバッファ最終以降の右側表示消去
567+ for(;x<twidth;x++){
568+ *(vp+attroffset)=0;
569+ *vp++=0;
570+ }
571+ }
572+ //バッファ最終以降の下側表示消去
573+ for(;y<EDITWIDTHY;y++){
574+ for(x=0;x<twidth;x++){
575+ *(vp+attroffset)=0;
576+ *vp++=0;
577+ }
578+ }
579+}
580+
581+void cursor_left(void){
582+//カーソルを1つ前に移動
583+//出力:下記変数を移動先の値に変更
584+//cursorbp,cursorix バッファ上のカーソル位置
585+//cx,cy 画面上のカーソル位置
586+//cx2 cxと同じ
587+//disptopbp,disptopix 画面左上のバッファ上の位置
588+
589+ _tbuf *bp;
590+ int ix;
591+ int i;
592+ int x;
593+
594+ //バッファ上のカーソル位置を1つ前に移動
595+ if(cursorix!=0) cursorix--;
596+ else while(1) {
597+ //1つ前のバッファの最後尾に移動、ただし空バッファは飛ばす
598+ if(cursorbp->prev==NULL) return; //テキスト全体先頭なので移動しない
599+ cursorbp=cursorbp->prev;
600+ if(cursorbp->n >0){
601+ cursorix=cursorbp->n-1;//バッファ最後尾
602+ break;
603+ }
604+ }
605+
606+ //カーソルおよび画面左上位置の更新
607+ if(cx>0){
608+ //左端でなければカーソルを単純に1つ左に移動して終了
609+ cx--;
610+ cx2=cx;
611+ return;
612+ }
613+ if(cy>0){
614+ //左端だが上端ではない場合
615+ if(cursorbp->Buf[cursorix]!='\n'){
616+ // 移動先が改行コードでない場合、カーソルは1つ上の行の右端に移動
617+ cx=twidth-1;
618+ cx2=cx;
619+ cy--;
620+ return;
621+ }
622+ //画面左上位置から最後尾のX座標をサーチ
623+ bp=disptopbp;
624+ ix=disptopix;
625+ x=0;
626+ while(ix!=cursorix || bp!=cursorbp){
627+ if(bp->n==0){
628+ //空バッファの場合次へ
629+ bp=bp->next;
630+ ix=0;
631+ continue;
632+ }
633+ if(bp->Buf[ix++]=='\n' || x>=twidth-1) x=0;
634+ else x++;
635+ if(ix >= bp->n){
636+ bp=bp->next;
637+ ix=0;
638+ }
639+ }
640+ cx=x;
641+ cx2=cx;
642+ cy--;
643+ line_no--;
644+ return;
645+ }
646+
647+ //左端かつ上端の場合
648+ if(cursorbp->Buf[cursorix]!='\n'){
649+ // 移動先が改行コードでない場合、カーソルは右端に移動
650+ // 画面左上位置は画面横幅分前に移動
651+ cx=twidth-1;
652+ cx2=cx;
653+ }
654+ else{
655+ //移動先が改行コードの場合
656+ //行頭(改行の次の文字またはバッファ先頭)と現在位置の文字数差を
657+ //画面横幅で割った余りがカーソルX座標
658+ bp=cursorbp;
659+ ix=cursorix;
660+ i=0;
661+ while(1){
662+ if(ix==0){
663+ if(bp->prev==NULL) break;
664+ bp=bp->prev;
665+ ix=bp->n;
666+ continue;
667+ }
668+ ix--;
669+ if(bp->Buf[ix]=='\n') break;
670+ i++;
671+ }
672+ cx=i % twidth;
673+ cx2=cx;
674+ line_no--;
675+ }
676+ //画面左上位置は現在位置からX座標分引いたところ
677+ bp=cursorbp;
678+ ix=cursorix;
679+ x=cx;
680+ while(x>0){
681+ if(ix==0){
682+ bp=bp->prev;
683+ ix=bp->n;
684+ continue;
685+ }
686+ ix--;
687+ x--;
688+ }
689+ disptopbp=bp;
690+ disptopix=ix;
691+}
692+void cursor_right(void){
693+//カーソルを1つ後ろに移動
694+//出力:下記変数を移動先の値に変更
695+//cursorbp,cursorix バッファ上のカーソル位置
696+//cx,cy 画面上のカーソル位置
697+//cx2 cxと同じ
698+//disptopbp,disptopix 画面左上のバッファ上の位置
699+
700+ _tbuf *bp;
701+ int ix;
702+ int i;
703+ int x;
704+ unsigned char c;
705+
706+ if(cursorix >= cursorbp->n){
707+ //バッファ最後尾の場合、次の先頭に移動
708+ bp=cursorbp;
709+ while(1) {
710+ //空バッファは飛ばす
711+ if(bp->next==NULL) return; //テキスト全体最後尾なので移動しない
712+ bp=bp->next;
713+ if(bp->n >0) break;
714+ }
715+ cursorbp=bp;
716+ cursorix=0;//バッファ先頭
717+ }
718+ c=cursorbp->Buf[cursorix++]; //バッファ上のカーソル位置のコードを読んで1つ後ろに移動
719+ if(c!='\n' && cx<twidth-1){
720+ //カーソル位置が改行でも右端でもない場合単純に1つ右に移動して終了
721+ cx++;
722+ cx2=cx;
723+ return;
724+ }
725+ cx=0; //カーソルを左端に移動
726+ cx2=cx;
727+ if(c=='\n') line_no++;
728+ if(cy<EDITWIDTHY-1){
729+ //下端でなければカーソルを次行に移動して終了
730+ cy++;
731+ return;
732+ }
733+ //下端の場合
734+ //画面左上位置を更新
735+ //改行コードまたは画面横幅超えるまでサーチ
736+ bp=disptopbp;
737+ ix=disptopix;
738+ x=0;
739+ while(x<twidth){
740+ if(ix >= bp->n){
741+ bp=bp->next;
742+ ix=0;
743+ continue;
744+ }
745+ if(bp->Buf[ix++]=='\n') break;
746+ x++;
747+ }
748+ disptopbp=bp;
749+ disptopix=ix;
750+}
751+void cursor_up(void){
752+//カーソルを1つ上に移動
753+//出力:下記変数を移動先の値に変更
754+//cursorbp,cursorix バッファ上のカーソル位置
755+//cx,cy 画面上のカーソル位置
756+//cx2 移動前のcxと同じ
757+//disptopbp,disptopix 画面左上のバッファ上の位置
758+
759+ _tbuf *bp;
760+ int ix;
761+ int i;
762+ int x;
763+ unsigned char c;
764+
765+ //画面幅分前に戻ったところがバッファ上カーソルの移動先
766+ //途中で改行コードがあれば別の手段で検索
767+ bp=cursorbp;
768+ ix=cursorix;
769+ i=cx2-cx;
770+ while(i<twidth){
771+ if(ix==0){
772+ if(bp->prev==NULL) return; //バッファ先頭までサーチしたら移動なし
773+ bp=bp->prev;
774+ ix=bp->n;
775+ continue;
776+ }
777+ ix--;
778+ if(bp->Buf[ix]=='\n') break;
779+ i++;
780+ }
781+ cursorbp=bp;
782+ cursorix=ix;
783+ //画面幅の間に改行コードがなかった場合
784+ if(i==twidth){
785+ cx=cx2;
786+ //画面上端でなければカーソルを1つ上に移動して終了
787+ if(cy>0){
788+ cy--;
789+ return;
790+ }
791+ //画面上端の場合、カーソル位置からX座標分戻ったところが画面左上位置
792+ x=cx;
793+ while(x>0){
794+ if(ix==0){
795+ bp=bp->prev;
796+ ix=bp->n;
797+ continue;
798+ }
799+ ix--;
800+ x--;
801+ }
802+ disptopbp=bp;
803+ disptopix=ix;
804+ return;
805+ }
806+ //改行が見つかった場合
807+ //行頭(改行の次の文字またはバッファ先頭)と現在位置の文字数差を
808+ //画面横幅で割った余りを求める
809+ line_no--;
810+ i=0;
811+ while(1){
812+ if(ix==0){
813+ if(bp->prev==NULL) break;
814+ bp=bp->prev;
815+ ix=bp->n;
816+ continue;
817+ }
818+ ix--;
819+ if(bp->Buf[ix]=='\n') break;
820+ i++;
821+ }
822+ x=i % twidth; //改行ブロックの最終行の右端
823+ bp=cursorbp;
824+ ix=cursorix;
825+ //バッファ上のカーソル位置は改行ブロックの最終行右端からカーソルX座標分戻る
826+ //最終行右端のほうが小さい場合、その場所をバッファ上のカーソル位置とする
827+ while(x>cx2){
828+ if(ix==0){
829+ bp=bp->prev;
830+ ix=bp->n;
831+ continue;
832+ }
833+ ix--;
834+ x--;
835+ }
836+ cursorbp=bp;
837+ cursorix=ix;
838+ cx=x; //cx2または改行ブロック最終行右端
839+ if(cy>0){
840+ //画面上端でなければカーソルを1つ上に移動して終了
841+ cy--;
842+ return;
843+ }
844+ //画面上端の場合
845+ //画面左上位置は現在位置からX座標分引いたところ
846+ while(x>0){
847+ if(ix==0){
848+ bp=bp->prev;
849+ ix=bp->n;
850+ continue;
851+ }
852+ ix--;
853+ x--;
854+ }
855+ disptopbp=bp;
856+ disptopix=ix;
857+}
858+void cursor_down(void){
859+//カーソルを1つ下に移動
860+//出力:下記変数を移動先の値に変更
861+//cursorbp,cursorix バッファ上のカーソル位置
862+//cx,cy 画面上のカーソル位置
863+//cx2 移動前のcxと同じ
864+//disptopbp,disptopix 画面左上のバッファ上の位置
865+
866+ _tbuf *bp;
867+ int ix;
868+ int x;
869+ unsigned char c;
870+
871+ //次行の先頭サーチ
872+ //カーソル位置から画面右端までの間に改行コードがあれば次の文字が先頭
873+ bp=cursorbp;
874+ ix=cursorix;
875+ x=cx;
876+ while(x<twidth){
877+ if(ix>=bp->n){
878+ if(bp->next==NULL) return; //バッファ最後までサーチしたら移動なし
879+ bp=bp->next;
880+ ix=0;
881+ continue;
882+ }
883+ c=bp->Buf[ix];
884+ ix++;
885+ x++;
886+ if(c=='\n'){
887+ line_no++;
888+ break;
889+ }
890+ }
891+ //次行先頭からcx2文字数分後ろにサーチ
892+ x=0;
893+ while(x<cx2){
894+ if(ix>=bp->n){
895+ if(bp->next==NULL) break; //バッファ最後の場合そこに移動
896+ bp=bp->next;
897+ ix=0;
898+ continue;
899+ }
900+ if(bp->Buf[ix]=='\n') break; //改行コードの場合そこに移動
901+ ix++;
902+ x++;
903+ }
904+ cursorbp=bp;
905+ cursorix=ix;
906+ cx=x;
907+ //画面下端でなければカーソルを1つ下に移動して終了
908+ if(cy<EDITWIDTHY-1){
909+ cy++;
910+ return;
911+ }
912+ //下端の場合
913+ //画面左上位置を更新
914+ //改行コードまたは画面横幅超えるまでサーチ
915+ bp=disptopbp;
916+ ix=disptopix;
917+ x=0;
918+ while(x<twidth){
919+ if(ix >= bp->n){
920+ bp=bp->next;
921+ ix=0;
922+ continue;
923+ }
924+ if(bp->Buf[ix++]=='\n') break;
925+ x++;
926+ }
927+ disptopbp=bp;
928+ disptopix=ix;
929+}
930+void cursor_home(void){
931+//カーソルを行先頭に移動
932+//出力:下記変数を移動先の値に変更
933+//cursorbp,cursorix バッファ上のカーソル位置
934+//cx,cx2 0
935+//cy 変更なし
936+//disptopbp,disptopix 画面左上のバッファ上の位置(変更なし)
937+
938+ //カーソルX座標分前に移動
939+ while(cx>0){
940+ if(cursorix==0){
941+ //空バッファは飛ばす
942+ cursorbp=cursorbp->prev;
943+ cursorix=cursorbp->n;
944+ continue;
945+ }
946+ cursorix--;
947+ cx--;
948+ }
949+ cx2=0;
950+}
951+void cursor_end(void){
952+//カーソルを行末に移動
953+//出力:下記変数を移動先の値に変更
954+//cursorbp,cursorix バッファ上のカーソル位置
955+//cx,cx2 行末
956+//cy 変更なし
957+//disptopbp,disptopix 画面左上のバッファ上の位置(変更なし)
958+
959+ //カーソルX座標を画面幅分後ろに移動
960+ //改行コードまたはバッファ最終があればそこに移動
961+ while(cx<twidth-1){
962+ if(cursorix>=cursorbp->n){
963+ //空バッファは飛ばす
964+ if(cursorbp->next==NULL) break;
965+ cursorbp=cursorbp->next;
966+ cursorix=0;
967+ continue;
968+ }
969+ if(cursorbp->Buf[cursorix]=='\n') break;
970+ cursorix++;
971+ cx++;
972+ }
973+ cx2=cx;
974+}
975+void cursor_pageup(void){
976+//PageUpキー
977+//最上行が最下行になるまでスクロール
978+//出力:下記変数を移動先の値に変更
979+//cursorbp,cursorix バッファ上のカーソル位置
980+//cx,cx2
981+//cy
982+//disptopbp,disptopix 画面左上のバッファ上の位置
983+
984+ _tbuf *bp;
985+ int ix;
986+ int i;
987+ int cy_old;
988+
989+ cy_old=cy;
990+ while(cy>0) cursor_up(); // cy==0になるまでカーソルを上に移動
991+ for(i=0;i<EDITWIDTHY-1;i++){
992+ //画面行数-1行分カーソルを上に移動
993+ bp=disptopbp;
994+ ix=disptopix;
995+ cursor_up();
996+ if(bp==disptopbp && ix==disptopix) break; //最上行で移動できなかった場合抜ける
997+ }
998+ //元のY座標までカーソルを下に移動、1行も動かなかった場合は最上行に留まる
999+ if(i>0) while(cy<cy_old) cursor_down();
1000+}
1001+void cursor_pagedown(void){
1002+//PageDownキー
1003+//最下行が最上行になるまでスクロール
1004+//出力:下記変数を移動先の値に変更
1005+//cursorbp,cursorix バッファ上のカーソル位置
1006+//cx,cx2
1007+//cy
1008+//disptopbp,disptopix 画面左上のバッファ上の位置
1009+
1010+ _tbuf *bp;
1011+ int ix;
1012+ int i;
1013+ int y;
1014+ int cy_old;
1015+
1016+ cy_old=cy;
1017+ while(cy<EDITWIDTHY-1){
1018+ // cy==EDITWIDTH-1になるまでカーソルを下に移動
1019+ y=cy;
1020+ cursor_down();
1021+ if(y==cy) break;// バッファ最下行で移動できなかった場合抜ける
1022+ }
1023+ for(i=0;i<EDITWIDTHY-1;i++){
1024+ //画面行数-1行分カーソルを下に移動
1025+ bp=disptopbp;
1026+ ix=disptopix;
1027+ cursor_down();
1028+ if(bp==disptopbp && ix==disptopix) break; //最下行で移動できなかった場合抜ける
1029+ }
1030+ //下端からさらに移動した行数分、カーソルを上に移動、1行も動かなかった場合は最下行に留まる
1031+ if(i>0) while(cy>cy_old) cursor_up();
1032+}
1033+void cursor_top(void){
1034+//カーソルをテキストバッファの先頭に移動
1035+ cursorbp=TBufstart;
1036+ cursorix=0;
1037+ cursorbp1=NULL; //範囲選択モード解除
1038+ disptopbp=cursorbp;
1039+ disptopix=cursorix;
1040+ cx=0;
1041+ cx2=0;
1042+ cy=0;
1043+ line_no=1;
1044+}
1045+
1046+int countarea(void){
1047+//テキストバッファの指定範囲の文字数をカウント
1048+//範囲は(cursorbp,cursorix)と(cursorbp1,cursorix1)で指定
1049+//後ろ側の一つ前の文字までをカウント
1050+ _tbuf *bp1,*bp2;
1051+ int ix1,ix2;
1052+ int n;
1053+
1054+ //範囲選択モードの場合、開始位置と終了の前後判断して
1055+ //bp1,ix1を開始位置、bp2,ix2を終了位置に設定
1056+ if(cy<cy1 || (cy==cy1 && cx<cx1)){
1057+ bp1=cursorbp;
1058+ ix1=cursorix;
1059+ bp2=cursorbp1;
1060+ ix2=cursorix1;
1061+ }
1062+ else{
1063+ bp1=cursorbp1;
1064+ ix1=cursorix1;
1065+ bp2=cursorbp;
1066+ ix2=cursorix;
1067+ }
1068+ n=0;
1069+ while(1){
1070+ if(bp1==bp2 && ix1==ix2) return n;
1071+ if(ix1 < bp1->n){
1072+ n++;
1073+ ix1++;
1074+ }
1075+ else{
1076+ bp1=bp1->next;
1077+ ix1=0;
1078+ }
1079+ }
1080+}
1081+void deletearea_len(_tbuf *bp,unsigned int ix,int n,int undo){
1082+//テキストバッファの指定位置から複数文字削除
1083+//bp,ix:削除開始位置
1084+//n:削除する文字数
1085+//undo:0:通常、2:アンドゥ中
1086+ unsigned char *p;
1087+ int i;
1088+
1089+ //選択範囲が最初のバッファの最後まである場合
1090+ if(n>=(bp->n - ix)){
1091+ if(!undo){
1092+ p=bp->Buf+ix;
1093+ for(i=ix;i < bp->n;i++) pushundomem(*p++); //アンドゥバッファに格納
1094+ }
1095+ n -= bp->n - ix; //削除文字数減
1096+ num-=bp->n - ix; //バッファ使用量を減数
1097+ bp->n=ix; //ix以降を削除
1098+ bp=bp->next;
1099+ if(bp==NULL) return;
1100+ ix=0;
1101+ }
1102+ //次のバッファ以降、選択範囲の終了位置が含まれないバッファは削除
1103+ while(n>=bp->n){
1104+ if(!undo){
1105+ p=bp->Buf;
1106+ for(i=0;i < bp->n;i++) pushundomem(*p++); //アンドゥバッファに格納
1107+ }
1108+ n-=bp->n; //削除文字数減
1109+ num-=bp->n; //バッファ使用量を減数
1110+ bp=deleteTBuf(bp); //バッファ削除して次のバッファに進む
1111+ if(bp==NULL) return;
1112+ }
1113+ //選択範囲の終了位置を含む場合、1文字ずつ削除
1114+ if(!undo) undo=1;
1115+ while(n>0){
1116+ deletechar(bp,ix,undo); //バッファから1文字削除(numは関数内で1減される)
1117+ n--;
1118+ }
1119+}
1120+void deletearea(void){
1121+//テキストバッファの指定範囲を削除
1122+//範囲は(cursorbp,cursorix)と(cursorbp1,cursorix1)で指定
1123+//後ろ側の一つ前の文字までを削除
1124+//削除後のカーソル位置は選択範囲の先頭にし、範囲選択モード解除する
1125+
1126+ _tbuf *bp;
1127+ int ix;
1128+ int n;
1129+
1130+ n=countarea(); //選択範囲の文字数カウント
1131+ if(n==0) return;
1132+
1133+ //範囲選択の開始位置と終了位置の前後を判断してカーソルを開始位置に設定
1134+ if(cy>cy1 || (cy==cy1 && cx>cx1)){
1135+ cursorbp=cursorbp1;
1136+ cursorix=cursorix1;
1137+ cx=cx1;
1138+ cy=cy1;
1139+ line_no=line_no1;
1140+ }
1141+ cx2=cx;
1142+ cursorbp1=NULL; //範囲選択モード解除
1143+
1144+ //bp,ixを開始位置に設定
1145+ bp=cursorbp;
1146+ ix=cursorix;
1147+
1148+ setundobuf(UNDO_CONTDEL,bp,ix,0,n); //アンドゥバッファ設定(連続削除開始)
1149+ deletearea_len(bp,ix,n,0); //n文字分削除
1150+ //アンドゥバッファに連続削除終了設定
1151+ pushundomem2(bpixtopos(bp,ix));
1152+ pushundomem2(n);
1153+ pushundomem(UNDO_CONTDEL);
1154+}
1155+void clipcopy(void){
1156+// 選択範囲をクリップボードにコピー
1157+ _tbuf *bp1,*bp2;
1158+ int ix1,ix2;
1159+ char *ps,*pd;
1160+
1161+ //範囲選択モードの場合、開始位置と終了の前後判断して
1162+ //bp1,ix1を開始位置、bp2,ix2を終了位置に設定
1163+ if(cy<cy1 || (cy==cy1 && cx<cx1)){
1164+ bp1=cursorbp;
1165+ ix1=cursorix;
1166+ bp2=cursorbp1;
1167+ ix2=cursorix1;
1168+ }
1169+ else{
1170+ bp1=cursorbp1;
1171+ ix1=cursorix1;
1172+ bp2=cursorbp;
1173+ ix2=cursorix;
1174+ }
1175+ ps=bp1->Buf+ix1;
1176+ pd=clipboard;
1177+ clipsize=0;
1178+ while(bp1!=bp2 || ix1!=ix2){
1179+ if(ix1 < bp1->n){
1180+ *pd++=*ps++;
1181+ clipsize++;
1182+ ix1++;
1183+ }
1184+ else{
1185+ bp1=bp1->next;
1186+ ps=bp1->Buf;
1187+ ix1=0;
1188+ }
1189+ }
1190+}
1191+void clippaste(void){
1192+// クリップボードから貼り付け
1193+ int n,i;
1194+ unsigned char *p;
1195+
1196+ if(clipsize==0 || num+clipsize>TBUFMAXSIZE) return;
1197+ setundobuf(UNDO_CONTINS,cursorbp,cursorix,0,clipsize); //アンドゥバッファ設定
1198+ p=clipboard;
1199+ for(n=clipsize;n>0;n--){
1200+ i=insertchar(cursorbp,cursorix,*p,1);
1201+ if(i>0){
1202+ //バッファ空きがあるのに挿入失敗の場合
1203+ gabagecollect2(); //全体ガベージコレクション
1204+ i=insertchar(cursorbp,cursorix,*p,1);//テキストバッファに1文字挿入
1205+ }
1206+ if(i!=0) break;//挿入失敗
1207+ cursor_right();//画面上、バッファ上のカーソル位置を1つ後ろに移動
1208+ p++;
1209+ }
1210+}
1211+void movecursor(int pos){
1212+// カーソルを現在の位置から任意の位置に移動
1213+// pos:移動したいテキストバッファ先頭からのバイト位置
1214+ int pos2,d;
1215+ pos2=bpixtopos(cursorbp,cursorix);
1216+ d=pos-pos2;
1217+ if(d==0) return;
1218+ if(d>0){
1219+ while(d>0){
1220+ cursor_right();
1221+ d--;
1222+ }
1223+ }
1224+ else{
1225+ while(d<0){
1226+ cursor_left();
1227+ d++;
1228+ }
1229+ }
1230+}
1231+void undoexec(){
1232+//アンドゥ実行
1233+ unsigned char c,c1;
1234+ _tbuf *bp;
1235+ unsigned short n,ix;
1236+ int pos;
1237+
1238+ if(undobuf_used==0) return; //アンドゥバッファ空
1239+ cursorbp1=NULL; //範囲選択解除
1240+ c=popundomem(); //アンドゥバッファ先頭の命令読み出し
1241+ switch(c){
1242+ case UNDO_INSERT: //1文字挿入
1243+ //カーソル移動し1文字削除
1244+ pos=popundomem2();
1245+ movecursor(pos);
1246+ bp=postobpix(pos,&ix);
1247+ deletechar(bp,ix,2);
1248+ popundomem(); //dummy read
1249+ break;
1250+ case UNDO_CONTINS: //連続挿入
1251+ //カーソル移動し連続数分削除
1252+ n=popundomem2();
1253+ pos=popundomem2();
1254+ movecursor(pos);
1255+ bp=postobpix(pos,&ix);
1256+ deletearea_len(bp,ix,n,2);
1257+ popundomem(); //dummy read
1258+ break;
1259+ case UNDO_CONTDEL: //連続削除
1260+ //カーソル移動し連続数分、コードを読み出して挿入
1261+ n=popundomem2();
1262+ pos=popundomem2();
1263+ movecursor(pos);
1264+ bp=postobpix(pos,&ix);
1265+ while(n>0){
1266+ insertchar(bp,ix,popundomem(),2);
1267+ n--;
1268+ }
1269+ popundomem2(); //dummy read
1270+ popundomem(); //dummy read
1271+ break;
1272+ case 0: //0の場合、次の1バイトが実際の有効なコード
1273+ c=popundomem();
1274+ default: //1文字削除(DEL、BS)、1文字上書き
1275+ //カーソル移動し1文字挿入(または上書き)
1276+ pos=popundomem2();
1277+ movecursor(pos);
1278+ bp=postobpix(pos,&ix);
1279+ c1=popundomem();
1280+ if(c1==UNDO_OVERWRITE){
1281+ overwritechar(bp,ix,c,2);
1282+ }
1283+ else{
1284+ insertchar(bp,ix,c,2);
1285+ if(c1==UNDO_BACKSPACE) cursor_right();
1286+ }
1287+ break;
1288+ }
1289+}
1290+
1291+void set_areamode(){
1292+//範囲選択モード開始時のカーソル開始位置グローバル変数設定
1293+ cursorbp1=cursorbp;
1294+ cursorix1=cursorix;
1295+ cx1=cx;
1296+ cy1=cy;
1297+ line_no1=line_no;
1298+}
1299+void save_cursor(void){
1300+//カーソル関連グローバル変数を一時避難
1301+ cursorbp_t=cursorbp;
1302+ cursorix_t=cursorix;
1303+ disptopbp_t=disptopbp;
1304+ disptopix_t=disptopix;
1305+ cx_t=cx;
1306+ cy_t=cy;
1307+ line_no_t=line_no;
1308+}
1309+void restore_cursor(void){
1310+//カーソル関連グローバル変数を一時避難場所から戻す
1311+ cursorbp=cursorbp_t;
1312+ cursorix=cursorix_t;
1313+ disptopbp=disptopbp_t;
1314+ disptopix=disptopix_t;
1315+ cx=cx_t;
1316+ cy=cy_t;
1317+ line_no=line_no_t;
1318+}
1319+
1320+int filesystemretry(){
1321+// SDファイルシステムの再初期化確認と実施
1322+// SDファイルへの保存や読み込み時にファイルエラーが発生した場合に呼び出す
1323+// 戻り値 0:初期化成功、-1:成功することなくEscapeで抜けた
1324+ unsigned short vk;
1325+ while(1){
1326+ setcursorcolor(COLOR_NORMALTEXT);
1327+ printstr((unsigned char *)Message3); //Retry / Quit
1328+ while(1){
1329+ inputchar(); //1文字入力待ち
1330+ vk=vkey & 0xff;
1331+ if(vk==VK_RETURN || vk==VK_SEPARATOR) break;
1332+ if(vk==VK_ESCAPE) return -1;
1333+ }
1334+ //ファイルシステム初期化
1335+ if(FSInit()!=FALSE) return 0; //成功
1336+ //エラーの場合
1337+ setcursorcolor(COLOR_ERRORTEXT);
1338+ printstr((unsigned char *)Message2);//File System Error
1339+ }
1340+}
1341+
1342+int sdfilecopy(char *sourcefile,char *distfile){
1343+// SDカード上のファイルをコピー
1344+// soucefile:コピー元ファイル名
1345+// distfile:コピー先ファイル名
1346+// 戻り値:正常終了 0、エラー終了時エラー番号
1347+ FSFILE *sfp,*dfp;
1348+ int n,er,c;
1349+ er=0;
1350+ sfp=FSfopen(sourcefile,"r");
1351+ if(sfp==NULL) return ERR_CANTFILEOPEN;
1352+ dfp=FSfopen(distfile,"w");
1353+ if(dfp==NULL){
1354+ FSfclose(sfp);
1355+ return ERR_CANTFILEOPEN;
1356+ }
1357+ c=0;
1358+ while(1){
1359+ if(c==0){
1360+ printchar('.');
1361+ c=100;
1362+ }
1363+ c--;
1364+ n=FSfread(filebuf,1,FILEBUFSIZE,sfp);
1365+ if(n==0) break;
1366+ if(FSfwrite(filebuf,1,n,dfp)!=n){
1367+ er=ERR_CANTWRITEFILE;
1368+ break;
1369+ }
1370+ }
1371+ FSfclose(sfp);
1372+ FSfclose(dfp);
1373+ return er;
1374+}
1375+int savetextfile(char *filename){
1376+// テキストバッファをテキストファイルに書き込み
1377+// 書き込み成功で0、失敗でエラーコード(負数)を返す
1378+ FSFILE *fp;
1379+ _tbuf *bp;
1380+ int ix,n,i,er;
1381+ unsigned char *ps,*pd;
1382+ er=0;//エラーコード
1383+ i=-1;
1384+ fp=FSfopen(filename,"w");
1385+ if(fp==NULL) return ERR_CANTFILEOPEN;
1386+ bp=TBufstart;
1387+ ix=0;
1388+ ps=bp->Buf;
1389+ do{
1390+ pd=filebuf;
1391+ n=0;
1392+ while(n<FILEBUFSIZE-1){
1393+ //改行コードが2バイトになることを考慮してバッファサイズ-1までとする
1394+ while(ix>=bp->n){
1395+ bp=bp->next;
1396+ if(bp==NULL){
1397+ break;
1398+ }
1399+ ix=0;
1400+ ps=bp->Buf;
1401+ }
1402+ if(bp==NULL) break;
1403+ if(*ps=='\n'){
1404+ *pd++='\r'; //改行コード0A→0D 0Aにする
1405+ n++;
1406+ }
1407+ *pd++=*ps++;
1408+ ix++;
1409+ n++;
1410+ }
1411+ if(n>0){
1412+ i=FSfwrite(filebuf,1,n,fp);
1413+ if(i!=n) er=ERR_CANTWRITEFILE;
1414+ }
1415+ } while(bp!=NULL && er==0);
1416+ FSfclose(fp);
1417+ return er;
1418+}
1419+int loadtextfile(char *filename){
1420+// テキストファイルをテキストバッファに読み込み
1421+// 読み込み成功で0、失敗でエラーコード(負数)を返す
1422+ FSFILE *fp;
1423+ _tbuf *bp;
1424+ int ix,n,i,er;
1425+ unsigned char *ps,*pd;
1426+ er=0;//エラーコード
1427+ fp=FSfopen(filename,"r");
1428+ if(fp==NULL) return ERR_CANTFILEOPEN;
1429+ inittextbuf();
1430+ bp=TextBuffer;
1431+ ix=0;
1432+ pd=bp->Buf;
1433+ do{
1434+ n=FSfread(filebuf,1,FILEBUFSIZE,fp);
1435+ ps=filebuf;
1436+ for(i=0;i<n;i++){
1437+ if(ix>=TBUFSIZE){
1438+ bp->n=TBUFSIZE;
1439+ bp=newTBuf(bp);
1440+ if(bp==NULL){
1441+ er=ERR_FILETOOBIG;
1442+ break;
1443+ }
1444+ ix=0;
1445+ pd=bp->Buf;
1446+ }
1447+ if(*ps=='\r') ps++; //改行コード0D 0A→0Aにする(単純に0D無視)
1448+ else{
1449+ *pd++=*ps++;
1450+ ix++;
1451+ num++;//バッファ総文字数
1452+ if(num>TBUFMAXSIZE){
1453+ er=ERR_FILETOOBIG;
1454+ break;
1455+ }
1456+ }
1457+ }
1458+ } while(n==FILEBUFSIZE && er==0);
1459+ if(bp!=NULL) bp->n=ix;//最後のバッファの文字数
1460+ FSfclose(fp);
1461+ if(er){
1462+ //エラー発生の場合バッファ、カーソル位置初期化
1463+ inittextbuf();
1464+ cursor_top();
1465+ }
1466+ return er;
1467+}
1468+int overwritecheck(char *fn){
1469+// ファイルの上書き確認
1470+// ファイルの存在をチェックし、存在する場合キーボードから上書き確認する
1471+// fn:ファイル名へのポインタ
1472+// 戻り値 0:存在しないまたは上書き、-1:上書きしない
1473+ SearchRec sr;
1474+ unsigned short vk;
1475+ if(FindFirst(fn,ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_ARCHIVE,&sr)) return 0; //ファイルが存在しない
1476+ setcursorcolor(COLOR_ERRORTEXT);
1477+ printstr(fn);
1478+ printstr(": File Exists\n");
1479+ setcursorcolor(COLOR_NORMALTEXT);
1480+ printstr("Ovewrite:[Enter] / Stop:[ESC]\n");
1481+ while(1){
1482+ inputchar(); //1文字入力待ち
1483+ vk=vkey & 0xff;
1484+ if(vk==VK_RETURN || vk==VK_SEPARATOR) return 0;
1485+ if(vk==VK_ESCAPE) return -1;
1486+ }
1487+}
1488+void printfilename(unsigned char x,unsigned char y,int f,int num_dir){
1489+// x,yの位置にファイル名またはディレクトリ名を表示
1490+
1491+ if(f==-2){
1492+ setcursor(x,y,COLOR_ERRORTEXT);
1493+ printchar('<');
1494+ printstr("New FILE");
1495+ printchar('>');
1496+ }
1497+ else if(f==-1){
1498+ setcursor(x,y,COLOR_ERRORTEXT);
1499+ printchar('<');
1500+ printstr("New Dir");
1501+ printchar('>');
1502+ }
1503+ else if(f<num_dir){
1504+ setcursor(x,y,COLOR_DIR);
1505+ printchar('[');
1506+ printstr(filenames[f]);
1507+ printchar(']');
1508+ }
1509+ else{
1510+ setcursor(x,y,COLOR_NORMALTEXT);
1511+ printstr(filenames[f]);
1512+ }
1513+}
1514+int select_dir_file(int filenum,int num_dir, unsigned char* msg){
1515+// filenames[]配列に読み込まれたファイルまたはディレクトリを画面表示しキーボードで選択する
1516+// filenum:ファイル+ディレクトリ数
1517+// num_dir:ディレクトリ数(filenames[]は先頭からnum_dir-1までがディレクトリ)
1518+// msg:画面上部に表示するメッセージ
1519+// 戻り値
1520+// filenames[]の選択されたファイルまたはディレクトリ番号
1521+// -1:新規ディレクトリ作成、tempfile[]にディレクトリ名
1522+// -2:新規ファイル作成、tempfile[]にファイル名
1523+// -3:ESCキーが押された
1524+ int top,f;
1525+ unsigned char *ps,*pd;
1526+ int x,y;
1527+ unsigned char vk;
1528+ unsigned char vm;
1529+
1530+ //ファイル一覧を画面に表示
1531+ vm=videomode;
1532+ set_videomode(VMODE_STDTEXT,0);
1533+ cls();
1534+ setcursor(0,0,COLOR_NORMALTEXT);
1535+ printstr(msg);
1536+ printstr(": ");
1537+ setcursorcolor(4);
1538+ printstr("Select&[Enter] / [ESC]\n");
1539+ for(f=-2;f<filenum;f++){
1540+ x=(f&1)*15+1;
1541+ y=(f+2)/2+1;
1542+ if(y>=twidthy-1) break;
1543+ printfilename(x,y,f,num_dir);
1544+ }
1545+ top=-2;//画面一番先頭のファイル番号
1546+ f=-2;//現在選択中のファイル番号
1547+ while(1){
1548+ setcursor((f&1)*15,(f-top)/2+1,5);
1549+ printchar(0x1c);// Right Arrow
1550+ cursor--;
1551+ while(1){
1552+ inputchar();
1553+ vk=vkey & 0xff;
1554+ if(vk) break;
1555+ }
1556+ printchar(' ');
1557+ setcursor(0,twidthy-1,COLOR_NORMALTEXT);
1558+ for(x=0;x<twidth-1;x++) printchar(' '); //最下行のステータス表示を消去
1559+ switch(vk){
1560+ case VK_UP:
1561+ case VK_NUMPAD8:
1562+ //上矢印キー
1563+ if(f>=0){
1564+ f-=2;
1565+ if(f<top){
1566+ //画面最上部の場合、下にスクロールして最上部にファイル名2つ表示
1567+ setcursor(twidth-1,twidthy-2,COLOR_NORMALTEXT);
1568+ while(cursor>=TVRAM+twidth*2){
1569+ *cursor=*(cursor-twidth);
1570+ *(cursor+attroffset)=*(cursor+attroffset-twidth);
1571+ cursor--;
1572+ }
1573+ while(cursor>=TVRAM+twidth) *cursor--=' ';
1574+ top-=2;
1575+ printfilename(1,1,top,num_dir);
1576+ printfilename(16,1,top+1,num_dir);
1577+ }
1578+ }
1579+ break;
1580+ case VK_DOWN:
1581+ case VK_NUMPAD2:
1582+ //下矢印キー
1583+ if(((f+2)&0xfffe)<filenum){
1584+ f+=2;
1585+ if(f>=filenum) f--;
1586+ if(f-top>=(twidthy-2)*2){
1587+ //画面最下部の場合、上にスクロールして最下部にファイル名1つor2つ表示
1588+ setcursor(0,1,COLOR_NORMALTEXT);
1589+ while(cursor<TVRAM+twidth*(twidthy-2)){
1590+ *cursor=*(cursor+twidth);
1591+ *(cursor+attroffset)=*(cursor+attroffset+twidth);
1592+ cursor++;
1593+ }
1594+ while(cursor<TVRAM+twidth*(twidthy-1)) *cursor++=' ';
1595+ top+=2;
1596+ printfilename(1,twidthy-2,f&0xfffe,num_dir);
1597+ if((f|1)<filenum){
1598+ printfilename(16,twidthy-2,f|1,num_dir);
1599+ }
1600+ }
1601+ }
1602+ break;
1603+ case VK_LEFT:
1604+ case VK_NUMPAD4:
1605+ //左矢印キー
1606+ if(f&1) f--;
1607+ break;
1608+ case VK_RIGHT:
1609+ case VK_NUMPAD6:
1610+ //右矢印キー
1611+ if((f&1)==0 && f+1<filenum) f++;
1612+ break;
1613+ case VK_RETURN: //Enterキー
1614+ case VK_SEPARATOR: //テンキーのEnter
1615+ if(f==-2){
1616+ //新規ファイル
1617+ setcursor(0,twidthy-1,COLOR_ERRORTEXT);
1618+ printstr("Input File Name: ");
1619+ setcursorcolor(COLOR_NORMALTEXT);
1620+ //ファイル名入力
1621+ *tempfile=0;
1622+ if(lineinput(tempfile,8+1+3)<0) break; //ESCキー
1623+ if(*tempfile==0) break; //ファイル名入力なし
1624+ }
1625+ else if(f==-1){
1626+ //新規ディレクトリ
1627+ setcursor(0,twidthy-1,COLOR_ERRORTEXT);
1628+ printstr("Input Dir Name: ");
1629+ setcursorcolor(COLOR_NORMALTEXT);
1630+ //ディレクトリ名入力
1631+ *tempfile=0;
1632+ if(lineinput(tempfile,8+1+3)<0) break; //ESCキー
1633+ if(FSmkdir(tempfile)){
1634+ setcursor(0,twidthy-1,COLOR_ERRORTEXT);
1635+ printstr("Cannot Make Directory ");
1636+ break;
1637+ }
1638+ }
1639+ else{
1640+ //ファイル名またはディレクトリ名をtempfileにコピー
1641+ ps=filenames[f];
1642+ pd=tempfile;
1643+ while(*ps) *pd++=*ps++;
1644+ *pd=0;
1645+ }
1646+ set_videomode(vm,0);
1647+ return f;
1648+ case VK_ESCAPE:
1649+ //ESCキー
1650+ set_videomode(vm,0);
1651+ return -3;
1652+ }
1653+ }
1654+}
1655+int getfilelist(int *p_num_dir){
1656+// カレントディレクトリでのディレクトリ、.BAS、.TXT、.INIファイル一覧を読み込む
1657+// *p_num_dir:ディレクトリ数を返す
1658+// filenames[]:ファイル名およびディレクトリ名一覧
1659+// 戻り値 ファイル+ディレクトリ数
1660+
1661+ unsigned char *ps,*pd;
1662+ int filenum;
1663+ SearchRec sr;
1664+ filenum=0;
1665+ //ディレクトリのサーチ
1666+ if(FindFirst("*.*",ATTR_DIRECTORY,&sr)==0){
1667+ do{
1668+ //filenames[]にディレクトリ名の一覧を読み込み
1669+ ps=sr.filename;
1670+ pd=filenames[filenum];
1671+ while(*ps!=0) *pd++=*ps++;
1672+ *pd=0;
1673+ filenum++;
1674+ }
1675+ while(!FindNext(&sr) && filenum<MAXFILENUM);
1676+ }
1677+ *p_num_dir=filenum;
1678+ if(filenum>=MAXFILENUM) return filenum;
1679+ //拡張子 BASファイルのサーチ
1680+ if(FindFirst("*.BAS",ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_ARCHIVE,&sr)==0){
1681+ do{
1682+ //filenames[]にファイル名の一覧を読み込み
1683+ ps=sr.filename;
1684+ pd=filenames[filenum];
1685+ while(*ps!=0) *pd++=*ps++;
1686+ *pd=0;
1687+ filenum++;
1688+ }
1689+ while(!FindNext(&sr) && filenum<MAXFILENUM);
1690+ }
1691+ if(filenum>=MAXFILENUM) return filenum;
1692+ //拡張子 TXTファイルのサーチ
1693+ if(FindFirst("*.TXT",ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_ARCHIVE,&sr)==0){
1694+ do{
1695+ //filenames[]にファイル名の一覧を読み込み
1696+ ps=sr.filename;
1697+ pd=filenames[filenum];
1698+ while(*ps!=0) *pd++=*ps++;
1699+ *pd=0;
1700+ filenum++;
1701+ }
1702+ while(!FindNext(&sr) && filenum<MAXFILENUM);
1703+ }
1704+ if(filenum>=MAXFILENUM) return filenum;
1705+ //拡張子 INIファイルのサーチ
1706+ if(FindFirst("*.INI",ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_ARCHIVE,&sr)==0){
1707+ do{
1708+ //filenames[]にファイル名の一覧を読み込み
1709+ ps=sr.filename;
1710+ pd=filenames[filenum];
1711+ while(*ps!=0) *pd++=*ps++;
1712+ *pd=0;
1713+ filenum++;
1714+ }
1715+ while(!FindNext(&sr) && filenum<MAXFILENUM);
1716+ }
1717+ return filenum;
1718+}
1719+void save_as(int ow){
1720+// 現在のテキストバッファの内容をSDカードに保存
1721+// ow 0:名前を付けて保存  1:上書き保存
1722+// ファイル名はグローバル変数currentfile[]
1723+// ファイル名はキーボードから変更可能
1724+// 成功した場合currentfileを更新
1725+
1726+ int er;
1727+ int filenum,num_dir,f;
1728+ unsigned char *ps,*pd;
1729+
1730+ cls();
1731+ setcursor(0,0,COLOR_NORMALTEXT);
1732+ printstr("Save To SD Card\n");
1733+ if(currentfile[0]==0) ow=0; //ファイル名が設定されていない場合名前を付けて保存
1734+
1735+ //currentfileからtempfileにコピー
1736+ ps=currentfile;
1737+ pd=tempfile;
1738+ while(*ps!=0) *pd++=*ps++;
1739+ *pd=0;
1740+
1741+ //カレントディレクトリを変数cwdpathにコピー
1742+ while(1){
1743+ if(FSgetcwd(cwdpath,PATHNAMEMAX)) break;
1744+ setcursorcolor(COLOR_ERRORTEXT);
1745+ printstr("Cannot Get Current Dir\n");
1746+ if(filesystemretry()) return; //ファイルシステム再初期化、あきらめた場合はreturnする
1747+ }
1748+ //現在のディレクトリのパスを表示
1749+ setcursorcolor(COLOR_NORMALTEXT);
1750+ printstr("Current Directory is\n");
1751+ printstr(cwdpath);
1752+ printchar('\n');
1753+ while(1){
1754+ if(ow==0){
1755+ printstr("Input File Name + [Enter]\n");
1756+ printstr("[ESC] Select File/Dir or Quit\n");
1757+ //ファイル名入力
1758+ if(lineinput(tempfile,8+1+3)<0){
1759+ //ESCキーが押された場合、ファイル選択、ディレクトリ変更画面または終了
1760+ while(1){
1761+ filenum=getfilelist(&num_dir); //ディレクトリ、ファイル名一覧を読み込み
1762+ f=select_dir_file(filenum,num_dir,"Save"); //ファイルの選択
1763+ cls();
1764+ if(f==-3){
1765+ //終了
1766+ FSchdir(cwdpath);//カレントディレクトリを元に戻す
1767+ return;
1768+ }
1769+ else if(f==-2){
1770+ //新規ファイル
1771+ if(overwritecheck(tempfile)==0) break;//上書きチェック
1772+ }
1773+ else if(f<num_dir){
1774+ //新規ディレクトリまたはディレクトリ変更
1775+ FSchdir(tempfile);//ディレクトリ変更して再度ファイル一覧へ
1776+ }
1777+ else break;
1778+ }
1779+ }
1780+ else{
1781+ if(*tempfile==0) continue; //NULL文字列の場合
1782+ if(overwritecheck(tempfile)) continue;
1783+ }
1784+ }
1785+ printstr("Writing...\n");
1786+ er=savetextfile(tempfile); //ファイル保存、er:エラーコード
1787+ if(er==0){
1788+ printstr("OK");
1789+ FSremove(TEMPFILENAME); //実行時に生成する一時ファイルを削除
1790+ //tempfileからcurrentfileにコピーして終了
1791+ ps=tempfile;
1792+ pd=currentfile;
1793+ while(*ps!=0) *pd++=*ps++;
1794+ *pd=0;
1795+ FSgetcwd(cwdpath,PATHNAMEMAX); //カレントパスを更新
1796+ edited=0; //編集済みフラグクリア
1797+ wait60thsec(60);//1秒待ち
1798+ return;
1799+ }
1800+ setcursorcolor(COLOR_ERRORTEXT);
1801+ if(er==ERR_CANTFILEOPEN) printstr("Bad File Name or File Error\n");
1802+ else printstr("Cannot Write\n");
1803+ if(filesystemretry()) return; //ファイルシステム再初期化、あきらめた場合はreturnする
1804+ }
1805+}
1806+
1807+void newtext(void){
1808+// 新規テキスト作成
1809+ unsigned char vk;
1810+ if(edited && num){
1811+ //最終保存後に編集済みの場合、保存の確認
1812+ cls();
1813+ setcursorcolor(COLOR_NORMALTEXT);
1814+ printstr("Save Editing File?\n");
1815+ printstr("Save:[Enter] / Not Save:[ESC]\n");
1816+ while(1){
1817+ inputchar(); //1文字キー入力待ち
1818+ vk=vkey & 0xff;
1819+ if(vk==VK_RETURN || vk==VK_SEPARATOR){
1820+ save_as(0); //名前を付けて保存
1821+ break;
1822+ }
1823+ else if(vk==VK_ESCAPE) break;
1824+ }
1825+ }
1826+ inittextbuf(); //テキストバッファ初期化
1827+ cursor_top(); //カーソルをテキストバッファの先頭に設定
1828+ currentfile[0]=0; //作業中ファイル名クリア
1829+}
1830+
1831+void msra(void){
1832+// Make Self-Running Application (自己実行アプリケーションの作成)
1833+// 最初にソースファイルを名前を付けて保存
1834+// 次にBASICシステムのHEXファイルをソースファイル名の拡張子をHEXにした名前でコピー
1835+
1836+ int er;
1837+ unsigned char *ps,*pd;
1838+ cls();
1839+ setcursor(0,0,COLOR_NORMALTEXT);
1840+ printstr("Make Self-Running Application\n\n");
1841+ printstr("(Work on Root Directory)\n");
1842+
1843+ //カレントディレクトリを変数cwdpathにコピー
1844+ while(1){
1845+ if(FSgetcwd(cwdpath,PATHNAMEMAX)) break;
1846+ setcursorcolor(COLOR_ERRORTEXT);
1847+ printstr("Cannot Get Current Dir\n");
1848+ if(filesystemretry()) return; //ファイルシステム再初期化、あきらめた場合はreturnする
1849+ }
1850+ while(1){
1851+ //カレントディレクトリをルートに変更
1852+ if(FSchdir((char *)ROOTDIR)==0) break;
1853+ setcursorcolor(COLOR_ERRORTEXT);
1854+ printstr("Cannot Change To Root Dir\n");
1855+ if(filesystemretry()) return; //ファイルシステム再初期化、あきらめた場合はreturnする
1856+ }
1857+ //currentfileからtempfileにコピー
1858+ ps=currentfile;
1859+ pd=tempfile;
1860+ while(*ps!=0) *pd++=*ps++;
1861+ *pd=0;
1862+
1863+ while(1){
1864+ setcursorcolor(COLOR_NORMALTEXT);
1865+ printstr("Input File Name (xxx.BAS)\n");
1866+ if(lineinput(tempfile,8+1+3)<0){
1867+ //ESCキーが押された
1868+ FSchdir(cwdpath); //カレントディレクトリを元に戻す
1869+ return;
1870+ }
1871+ ps=tempfile;
1872+ while(*ps!='.' && *ps!=0) ps++;
1873+ if(ps+4>=tempfile+13 ||
1874+ *ps!='.' ||
1875+ (*(ps+1)!='b' && *(ps+1)!='B') ||
1876+ (*(ps+2)!='a' && *(ps+2)!='A') ||
1877+ (*(ps+3)!='s' && *(ps+3)!='S') ||
1878+ *(ps+4)!=0){
1879+ setcursorcolor(COLOR_ERRORTEXT);
1880+ printstr("File Name Must Be xxx.BAS\n");
1881+ continue;
1882+ }
1883+ if(overwritecheck(tempfile)) continue;
1884+ printstr("Writing BASIC File\n");
1885+ er=savetextfile(tempfile); //ファイル保存、er:エラーコード
1886+ if(er==0) break;
1887+ setcursorcolor(COLOR_ERRORTEXT);
1888+ if(er==ERR_CANTFILEOPEN) printstr("Bad File Name or File Error\n");
1889+ else printstr("Cannot Write\n");
1890+
1891+ //ファイルシステム再初期化、あきらめた場合はreturnする
1892+ if(filesystemretry()){
1893+ if(FSchdir(cwdpath)){
1894+ cwdpath[0]='\\';
1895+ cwdpath[1]=0;
1896+ }
1897+ return;
1898+ }
1899+ }
1900+ printstr("OK\n\n");
1901+ FSremove(TEMPFILENAME); //実行時に生成する一時ファイルを削除
1902+ //tempfileからcurrentfileにコピーして終了
1903+ ps=tempfile;
1904+ pd=currentfile;
1905+ while(*ps!=0) *pd++=*ps++;
1906+ *pd=0;
1907+ edited=0; //編集済みフラグクリア
1908+ // 拡張子をHEXにしてBASICシステムファイルをコピー
1909+ *(ps-3)='H';
1910+ *(ps-2)='E';
1911+ *(ps-1)='X';
1912+ if(overwritecheck(tempfile)) return;
1913+ printstr("Copying\n");
1914+ printstr(HEXFILE);
1915+ printstr(" To ");
1916+ printstr(tempfile);
1917+ printstr("\nWait For A While");
1918+ er=sdfilecopy(HEXFILE,tempfile);
1919+ if(FSchdir(cwdpath)){
1920+ cwdpath[0]='\\';
1921+ cwdpath[1]=0;
1922+ }
1923+ if(er==0){
1924+ printstr("\nDone");
1925+ wait60thsec(120);//2秒待ち
1926+ return;
1927+ }
1928+ setcursorcolor(COLOR_ERRORTEXT);
1929+ if(er==ERR_CANTFILEOPEN){
1930+ printstr(HEXFILE);
1931+ printstr(" Not Found\n");
1932+ }
1933+ else if(er==ERR_CANTWRITEFILE){
1934+ printstr("Write Error\n");
1935+ }
1936+ setcursorcolor(COLOR_NORMALTEXT);
1937+ printstr((unsigned char *)Message1);// Hit Any Key
1938+ inputchar(); //1文字入力待ち
1939+ return;
1940+}
1941+int fileload(void){
1942+// SDカードからファイルを選択して読み込み
1943+// currenfile[]にファイル名を記憶
1944+// 対象ファイル拡張子 BASおよびTXT
1945+// 戻り値 0:読み込みを行った -1:読み込みなし
1946+ int filenum,f,er;
1947+ unsigned char *ps,*pd;
1948+ unsigned char vk;
1949+ int num_dir;//ディレクトリ数
1950+
1951+ //ファイルの一覧をSDカードから読み出し
1952+ cls();
1953+ if(edited && num){
1954+ //最終保存後に編集済みの場合、保存の確認
1955+ setcursorcolor(COLOR_NORMALTEXT);
1956+ printstr("Save Program Before Load?\n");
1957+ printstr("Save:[Enter] / Not Save:[ESC]\n");
1958+ while(1){
1959+ inputchar(); //1文字キー入力待ち
1960+ vk=vkey & 0xff;
1961+ if(vk==VK_RETURN || vk==VK_SEPARATOR){
1962+ save_as(0); //名前を付けて保存
1963+ break;
1964+ }
1965+ else if(vk==VK_ESCAPE) break;
1966+ }
1967+ }
1968+ //カレントディレクトリを変数cwdpathにコピー
1969+ while(1){
1970+ if(FSgetcwd(cwdpath,PATHNAMEMAX)) break;
1971+ setcursorcolor(COLOR_ERRORTEXT);
1972+ printstr("Cannot Get Current Dir\n");
1973+ if(filesystemretry()) return -1; //ファイルシステム再初期化、あきらめた場合はreturnする
1974+ }
1975+ while(1){
1976+ filenum=getfilelist(&num_dir); //ディレクトリ、ファイル名一覧を読み込み
1977+ if(filenum==0){
1978+ setcursorcolor(COLOR_ERRORTEXT);
1979+ printstr(".BAS or .TXT File Not Found\n");
1980+ printstr((unsigned char *)Message1);// Hit Any Key
1981+ inputchar(); //1文字入力待ち
1982+ FSchdir(cwdpath);//カレントディレクトリを元に戻す
1983+ return -1;
1984+ }
1985+ //ファイルの選択
1986+ f=select_dir_file(filenum,num_dir,"Load");
1987+ if(f==-3){
1988+ //読み込まずに終了
1989+ FSchdir(cwdpath);//カレントディレクトリを元に戻す
1990+ return -1;
1991+ }
1992+ else if(f==-2){
1993+ //新規ファイルまたはファイル名を入力して読み込み
1994+ er=loadtextfile(tempfile); //テキストバッファにファイル読み込み
1995+ if(er==ERR_CANTFILEOPEN){
1996+ //ファイルが存在しない場合、新規テキスト
1997+ edited=0;
1998+ newtext();
1999+ }
2000+ else if(er==ERR_FILETOOBIG){
2001+ //ファイルサイズエラーの場合、選択画面に戻る
2002+ setcursor(0,twidthy-1,COLOR_ERRORTEXT);
2003+ printstr("File Too Big ");
2004+ wait60thsec(60);//1秒待ち
2005+ continue;
2006+ }
2007+ //currenfile[]にファイル名をコピー
2008+ ps=tempfile;
2009+ pd=currentfile;
2010+ while(*ps) *pd++=*ps++;
2011+ *pd=0;
2012+ FSgetcwd(cwdpath,PATHNAMEMAX);//cwdpathをカレントディレクトリのパスに変更
2013+ return 0;
2014+ }
2015+ else if(f<num_dir){
2016+ //新規ディレクトリまたはディレクトリ変更して、再度ファイル一覧画面へ
2017+ FSchdir(tempfile);
2018+ }
2019+ else{
2020+ er=loadtextfile(filenames[f]); //テキストバッファにファイル読み込み
2021+ if(er==0){
2022+ //cwdpath[]、currenfile[]にパス、ファイル名をコピーして終了
2023+ FSgetcwd(cwdpath,PATHNAMEMAX);
2024+ ps=filenames[f];
2025+ pd=currentfile;
2026+ while(*ps!=0) *pd++=*ps++;
2027+ *pd=0;
2028+ return 0;
2029+ }
2030+ setcursor(0,twidthy-1,COLOR_ERRORTEXT);
2031+ if(er==ERR_CANTFILEOPEN) printstr("Cannot Open File ");
2032+ else if(er=ERR_FILETOOBIG) printstr("File Too Big ");
2033+ wait60thsec(60);//1秒待ち
2034+ }
2035+ }
2036+}
2037+void changewidth(void){
2038+// 画面幅の切り替え
2039+ if(videomode==VMODE_STDTEXT) set_videomode(VMODE_WIDETEXT,0);
2040+ else if(videomode==VMODE_WIDETEXT) set_videomode(VMODE_MONOTEXT,0);
2041+ else set_videomode(VMODE_STDTEXT,0);
2042+ cursor_top(); //カーソルをテキストバッファの先頭に設定
2043+ redraw(); //再描画
2044+}
2045+void run(int test){
2046+//KM-BASICコンパイル&実行
2047+// test 0:コンパイルと実行、0以外:コンパイルのみで終了
2048+ int er,er2;
2049+ FSFILE *fp;
2050+ unsigned int disptoppos,cursorpos;
2051+ unsigned char widthmode;
2052+ int i,edited1;
2053+ _tbuf *bp;
2054+ unsigned short ix;
2055+ unsigned char *p;
2056+
2057+ cls();
2058+ setcursor(0,0,COLOR_NORMALTEXT);
2059+ while(1){
2060+ //カレントディレクトリをルートに変更
2061+ if(FSchdir((char *)ROOTDIR)){
2062+ setcursorcolor(COLOR_ERRORTEXT);
2063+ printstr("Cannot Change To Root Dir\n");
2064+ if(filesystemretry()) return; //ファイルシステム再初期化、あきらめた場合はreturnする
2065+ continue;
2066+ }
2067+ //ルートディレクトリのパス名保存ファイルに実行時パスを保存
2068+ fp=FSfopen(WORKDIRFILE,"w");
2069+ if(fp==NULL){
2070+ setcursorcolor(COLOR_ERRORTEXT);
2071+ printstr("Cannot Open Work Dir File\n");
2072+ if(filesystemretry()){
2073+ //ファイルシステム再初期化、あきらめた場合はカレントディレクトリを戻しreturnする
2074+ FSchdir(cwdpath);
2075+ return;
2076+ }
2077+ continue;
2078+ }
2079+ for(p=cwdpath;*p;p++) ;
2080+ er=FSfwrite(cwdpath,1,p-cwdpath+1,fp);
2081+ FSfclose(fp);
2082+ if(er!=p-cwdpath+1){
2083+ FSremove(WORKDIRFILE);
2084+ setcursorcolor(COLOR_ERRORTEXT);
2085+ printstr("Cannot Write Work Dir File\n");
2086+ if(filesystemretry()){
2087+ //ファイルシステム再初期化、あきらめた場合はカレントディレクトリを戻しreturnする
2088+ FSchdir(cwdpath);
2089+ return;
2090+ }
2091+ continue;
2092+ }
2093+ break;
2094+ }
2095+ while(1){
2096+ //カレントディレクトリを元に戻す
2097+ if(FSchdir(cwdpath)){
2098+ setcursorcolor(COLOR_ERRORTEXT);
2099+ printstr("Cannot Change To CWD\n");
2100+ if(filesystemretry()) return; //ファイルシステム再初期化、あきらめた場合はreturnする
2101+ continue;
2102+ }
2103+ //実行用引渡しファイルに保存
2104+ if(savetextfile(TEMPFILENAME)){
2105+ setcursorcolor(COLOR_ERRORTEXT);
2106+ printstr("Cannot Write To SD Card\n");
2107+ if(filesystemretry()) return; //ファイルシステム再初期化、あきらめた場合はreturnする
2108+ continue;
2109+ }
2110+ break;
2111+ }
2112+
2113+ //カーソル位置、画面表示位置、画面モードの保存
2114+ disptoppos=bpixtopos(disptopbp,disptopix);
2115+ cursorpos=bpixtopos(cursorbp,cursorix);
2116+ widthmode=videomode;
2117+ edited1=edited; //編集済みフラグの一時退避
2118+ set_videomode(VMODE_T30,0);//30文字モードに設定
2119+
2120+ // Enable Break key
2121+ g_disable_break=0;
2122+ //KM-BASIC実行
2123+ er2=runbasic(TEMPFILENAME,test);
2124+
2125+ stopPCG();//システムフォントに戻す
2126+ setcursorcolor(COLOR_NORMALTEXT);
2127+ printchar('\n');
2128+ printstr((unsigned char *)Message1);// Hit Any Key
2129+ do ps2readkey(); //キーバッファが空になるまで読み出し
2130+ while(vkey!=0);
2131+ inputchar(); //1文字入力待ち
2132+ stop_music(); //音楽再生停止
2133+ init_composite(); //パレット初期化のため画面初期化
2134+
2135+ //画面モードを戻す
2136+ set_videomode(widthmode,0);
2137+
2138+ FSgetcwd(cwdpath,PATHNAMEMAX);//カレントディレクトリパス変数を戻す
2139+ while(1){
2140+ //カレントディレクトリをルートに変更
2141+ if(FSchdir((char *)ROOTDIR)){
2142+ setcursorcolor(COLOR_ERRORTEXT);
2143+ printstr("Cannot Change To Root Dir\n");
2144+ filesystemretry(); //ファイルシステム再初期化
2145+ continue;
2146+ }
2147+ //ルートディレクトリのパス名保存ファイルからパス名を読み出し
2148+ fp=FSfopen(WORKDIRFILE,"r");
2149+ if(fp==NULL){
2150+ setcursorcolor(COLOR_ERRORTEXT);
2151+ printstr("Cannot Open Work Dir File\n");
2152+ filesystemretry(); //ファイルシステム再初期化
2153+ continue;
2154+ }
2155+ er=FSfread(cwdpath,1,PATHNAMEMAX,fp);
2156+ FSfclose(fp);
2157+ if(er<=0){
2158+ setcursorcolor(COLOR_ERRORTEXT);
2159+ printstr("Cannot Read Work Dir File\n");
2160+ filesystemretry(); //ファイルシステム再初期化
2161+ continue;
2162+ }
2163+ FSremove(WORKDIRFILE); //パス名保存ファイル削除
2164+ break;
2165+ }
2166+ while(1){
2167+ //カレントディレクトリを元に戻す
2168+ if(FSchdir(cwdpath)){
2169+ setcursorcolor(COLOR_ERRORTEXT);
2170+ printstr("Cannot Change To CWD\n");
2171+ filesystemretry(); //ファイルシステム再初期化
2172+ continue;
2173+ }
2174+ //実行用引渡しファイルから元に戻す
2175+ if(loadtextfile(TEMPFILENAME)){
2176+ setcursorcolor(COLOR_ERRORTEXT);
2177+ printstr("Cannot Load From SD Card\n");
2178+ filesystemretry(); //ファイルシステム再初期化
2179+ continue;
2180+ }
2181+ break;
2182+ }
2183+ if(er2<=0){
2184+ //正常終了またはファイルエラーまたはリンクエラーの場合
2185+ //カーソルを元の位置に設定
2186+ disptopbp=postobpix(disptoppos,&disptopix);
2187+ cursorbp=postobpix(cursorpos,&cursorix);
2188+ }
2189+ else{
2190+ //コンパイルエラーの場合
2191+ //カーソルをエラー行で画面トップに移動
2192+ disptopbp=linetobpix(er2,&disptopix);
2193+ cursorbp=disptopbp;
2194+ cursorix=disptopix;
2195+ cx=0;
2196+ cx2=0;
2197+ cy=0;
2198+ line_no=er2;
2199+ //中央になるようスクロール
2200+ for(i=0;i<EDITWIDTHY/2;i++){
2201+ //画面行数半分カーソルを上に移動
2202+ bp=disptopbp;
2203+ ix=disptopix;
2204+ cursor_up();
2205+ if(bp==disptopbp && ix==disptopix) break; //最上行で移動できなかった場合抜ける
2206+ }
2207+ for(;i>0;i--) cursor_down(); //元のY座標までカーソルを下に移動
2208+ }
2209+ cursorbp1=NULL; //範囲選択モード解除
2210+ clipsize=0; //クリップボードクリア
2211+ edited=edited1;
2212+ FSremove(TEMPFILENAME);
2213+}
2214+void displaybottomline(void){
2215+//エディター画面最下行の表示
2216+ unsigned char *p;
2217+ unsigned char c;
2218+ int t;
2219+ p=cursor; //カーソル位置の退避
2220+ c=cursorcolor;
2221+ if(shiftkeys() & CHK_SHIFT){
2222+ if(videomode!=VMODE_MONOTEXT){
2223+ setcursor(0,twidthy-1,COLOR_BOTTOMLINE);
2224+ printstr("NEW |MSRA |WIDTH|TEST | ");
2225+ }
2226+ else{
2227+ setcursor(0,twidthy-1,COLOR_INV);
2228+ printstr(" NEW \x87 MSRA \x87 WIDTH\x87 TEST \x87\x87");
2229+ }
2230+ setcursorcolor(COLOR_ERRORTEXT);
2231+ t=TBUFMAXSIZE-num;
2232+ if(t==0) t=1;
2233+ while(t<10000){
2234+ printchar(' ');
2235+ t*=10;
2236+ }
2237+ printstr("LEFT:");
2238+ printnum(TBUFMAXSIZE-num);
2239+ }
2240+ else{
2241+ if(videomode!=VMODE_MONOTEXT){
2242+ setcursor(0,twidthy-1,COLOR_BOTTOMLINE);
2243+ printstr("LOAD |SAVE | |RUN | ");
2244+ }
2245+ else{
2246+ setcursor(0,twidthy-1,COLOR_INV);
2247+ printstr(" LOAD \x87 SAVE \x87 \x87 RUN \x87\x87");
2248+ }
2249+ setcursorcolor(COLOR_ERRORTEXT);
2250+ t=line_no;
2251+ if(t==0) t=1;
2252+ while(t<10000){
2253+ printchar(' ');
2254+ t*=10;
2255+ }
2256+ printstr("LINE:");
2257+ printnum(line_no);
2258+ }
2259+ cursor=p; //カーソル位置戻し
2260+ cursorcolor=c;
2261+}
2262+void normal_code_process(unsigned char k){
2263+// 通常文字入力処理
2264+// k:入力された文字コード
2265+ int i;
2266+
2267+ edited=1; //編集済みフラグ
2268+ if(insertmode || k=='\n' || cursorbp1!=NULL){ //挿入モード
2269+ if(cursorbp1!=NULL) deletearea();//選択範囲を削除
2270+ i=insertchar(cursorbp,cursorix,k,0);//テキストバッファに1文字挿入
2271+ if(i>0){
2272+ //バッファ空きがあるのに挿入失敗の場合
2273+ gabagecollect2(); //全体ガベージコレクション
2274+ i=insertchar(cursorbp,cursorix,k,0);//テキストバッファに1文字挿入
2275+ }
2276+ if(i==0) cursor_right();//画面上、バッファ上のカーソル位置を1つ後ろに移動
2277+ }
2278+ else{ //上書きモード
2279+ i=overwritechar(cursorbp,cursorix,k,0);//テキストバッファに1文字上書き
2280+ if(i>0){
2281+ //バッファ空きがあるのに上書き(挿入)失敗の場合
2282+ //(行末やバッファ最後尾では挿入)
2283+ gabagecollect2(); //全体ガベージコレクション
2284+ i=overwritechar(cursorbp,cursorix,k,0);//テキストバッファに1文字上書き
2285+ }
2286+ if(i==0) cursor_right();//画面上、バッファ上のカーソル位置を1つ後ろに移動
2287+ }
2288+}
2289+void control_code_process(unsigned char k,unsigned char sh){
2290+// 制御文字入力処理
2291+// k:制御文字の仮想キーコード
2292+// sh:シフト関連キー状態
2293+
2294+ save_cursor(); //カーソル関連変数退避(カーソル移動できなかった場合戻すため)
2295+ switch(k){
2296+ case VK_LEFT:
2297+ case VK_NUMPAD4:
2298+ //シフトキー押下していなければ範囲選択モード解除(NumLock+シフト+テンキーでも解除)
2299+ if((sh & CHK_SHIFT)==0 || (k==VK_NUMPAD4) && (sh & CHK_NUMLK)) cursorbp1=NULL;
2300+ else if(cursorbp1==NULL) set_areamode(); //範囲選択モードでなければ範囲選択モード開始
2301+ if(sh & CHK_CTRL){
2302+ //CTRL+左矢印でHome
2303+ cursor_home();
2304+ break;
2305+ }
2306+ cursor_left();
2307+ if(cursorbp1!=NULL && (disptopbp!=disptopbp_t || disptopix!=disptopix_t)){
2308+ //範囲選択モードで画面スクロールがあった場合
2309+ if(cy1<EDITWIDTHY-1) cy1++; //範囲スタート位置もスクロール
2310+ else restore_cursor(); //カーソル位置を戻す(画面範囲外の範囲選択禁止)
2311+ }
2312+ break;
2313+ case VK_RIGHT:
2314+ case VK_NUMPAD6:
2315+ //シフトキー押下していなければ範囲選択モード解除(NumLock+シフト+テンキーでも解除)
2316+ if((sh & CHK_SHIFT)==0 || (k==VK_NUMPAD6) && (sh & CHK_NUMLK)) cursorbp1=NULL;
2317+ else if(cursorbp1==NULL) set_areamode(); //範囲選択モードでなければ範囲選択モード開始
2318+ if(sh & CHK_CTRL){
2319+ //CTRL+右矢印でEnd
2320+ cursor_end();
2321+ break;
2322+ }
2323+ cursor_right();
2324+ if(cursorbp1!=NULL && (disptopbp!=disptopbp_t || disptopix!=disptopix_t)){
2325+ //範囲選択モードで画面スクロールがあった場合
2326+ if(cy1>0) cy1--; //範囲スタート位置もスクロール
2327+ else restore_cursor(); //カーソル位置を戻す(画面範囲外の範囲選択禁止)
2328+ }
2329+ break;
2330+ case VK_UP:
2331+ case VK_NUMPAD8:
2332+ //シフトキー押下していなければ範囲選択モード解除(NumLock+シフト+テンキーでも解除)
2333+ if((sh & CHK_SHIFT)==0 || (k==VK_NUMPAD8) && (sh & CHK_NUMLK)) cursorbp1=NULL;
2334+ else if(cursorbp1==NULL) set_areamode(); //範囲選択モードでなければ範囲選択モード開始
2335+ cursor_up();
2336+ if(cursorbp1!=NULL && (disptopbp!=disptopbp_t || disptopix!=disptopix_t)){
2337+ //範囲選択モードで画面スクロールがあった場合
2338+ if(cy1<EDITWIDTHY-1) cy1++; //範囲スタート位置もスクロール
2339+ else restore_cursor(); //カーソル位置を戻す(画面範囲外の範囲選択禁止)
2340+ }
2341+ break;
2342+ case VK_DOWN:
2343+ case VK_NUMPAD2:
2344+ //シフトキー押下していなければ範囲選択モード解除(NumLock+シフト+テンキーでも解除)
2345+ if((sh & CHK_SHIFT)==0 || (k==VK_NUMPAD2) && (sh & CHK_NUMLK)) cursorbp1=NULL;
2346+ else if(cursorbp1==NULL) set_areamode(); //範囲選択モードでなければ範囲選択モード開始
2347+ cursor_down();
2348+ if(cursorbp1!=NULL && (disptopbp!=disptopbp_t || disptopix!=disptopix_t)){
2349+ //範囲選択モードで画面スクロールがあった場合
2350+ if(cy1>0) cy1--; //範囲スタート位置もスクロール
2351+ else restore_cursor(); //カーソル位置を戻す(画面範囲外の範囲選択禁止)
2352+ }
2353+ break;
2354+ case VK_HOME:
2355+ case VK_NUMPAD7:
2356+ //シフトキー押下していなければ範囲選択モード解除(NumLock+シフト+テンキーでも解除)
2357+ if((sh & CHK_SHIFT)==0 || (k==VK_NUMPAD7) && (sh & CHK_NUMLK)) cursorbp1=NULL;
2358+ else if(cursorbp1==NULL) set_areamode(); //範囲選択モードでなければ範囲選択モード開始
2359+ cursor_home();
2360+ break;
2361+ case VK_END:
2362+ case VK_NUMPAD1:
2363+ //シフトキー押下していなければ範囲選択モード解除(NumLock+シフト+テンキーでも解除)
2364+ if((sh & CHK_SHIFT)==0 || (k==VK_NUMPAD1) && (sh & CHK_NUMLK)) cursorbp1=NULL;
2365+ else if(cursorbp1==NULL) set_areamode(); //範囲選択モードでなければ範囲選択モード開始
2366+ cursor_end();
2367+ break;
2368+ case VK_PRIOR: // PageUpキー
2369+ case VK_NUMPAD9:
2370+ //シフト+PageUpは無効(NumLock+シフト+「9」除く)
2371+ if((sh & CHK_SHIFT) && ((k!=VK_NUMPAD9) || ((sh & CHK_NUMLK)==0))) break;
2372+ cursorbp1=NULL; //範囲選択モード解除
2373+ cursor_pageup();
2374+ break;
2375+ case VK_NEXT: // PageDownキー
2376+ case VK_NUMPAD3:
2377+ //シフト+PageDownは無効(NumLock+シフト+「3」除く)
2378+ if((sh & CHK_SHIFT) && ((k!=VK_NUMPAD3) || ((sh & CHK_NUMLK)==0))) break;
2379+ cursorbp1=NULL; //範囲選択モード解除
2380+ cursor_pagedown();
2381+ break;
2382+ case VK_DELETE: //Deleteキー
2383+ case VK_DECIMAL: //テンキーの「.」
2384+ edited=1; //編集済みフラグ
2385+ if(cursorbp1!=NULL) deletearea();//選択範囲を削除
2386+ else deletechar(cursorbp,cursorix,0);
2387+ break;
2388+ case VK_BACK: //BackSpaceキー
2389+ edited=1; //編集済みフラグ
2390+ if(cursorbp1!=NULL){
2391+ deletearea();//選択範囲を削除
2392+ break;
2393+ }
2394+ if(cursorix==0 && cursorbp->prev==NULL) break; //バッファ先頭では無視
2395+ cursor_left();
2396+ deletechar(cursorbp,cursorix,-1);
2397+ break;
2398+ case VK_INSERT:
2399+ case VK_NUMPAD0:
2400+ insertmode^=1; //挿入モード、上書きモードを切り替え
2401+ break;
2402+ case 'C':
2403+ //CTRL+C、クリップボードにコピー
2404+ if(cursorbp1!=NULL && (sh & CHK_CTRL)) clipcopy();
2405+ break;
2406+ case 'X':
2407+ //CTRL+X、クリップボードに切り取り
2408+ if(cursorbp1!=NULL && (sh & CHK_CTRL)){
2409+ clipcopy();
2410+ deletearea(); //選択範囲の削除
2411+ edited=1; //編集済みフラグ
2412+ }
2413+ break;
2414+ case 'V':
2415+ //CTRL+V、クリップボードから貼り付け
2416+ if((sh & CHK_CTRL)==0) break;
2417+ if(clipsize==0) break;
2418+ edited=1; //編集済みフラグ
2419+ if(cursorbp1!=NULL){
2420+ //範囲選択している時は削除してから貼り付け
2421+ if(num-countarea()+clipsize<=TBUFMAXSIZE){ //バッファ空き容量チェック
2422+ deletearea();//選択範囲を削除
2423+ clippaste();//クリップボード貼り付け
2424+ }
2425+ }
2426+ else{
2427+ if(num+clipsize<=TBUFMAXSIZE){ //バッファ空き容量チェック
2428+ clippaste();//クリップボード貼り付け
2429+ }
2430+ }
2431+ break;
2432+ case 'S':
2433+ //CTRL+S、SDカードに保存
2434+ if(num==0) break;
2435+ if(sh & CHK_CTRL) save_as(1); //上書き保存
2436+ break;
2437+ case 'O':
2438+ //CTRL+O、ファイル読み込み
2439+ if(sh & CHK_CTRL){
2440+ if(fileload()==0){ //ファイルを選択して読み込み
2441+ //読み込みを行った場合、カーソル位置を先頭に
2442+ cursor_top();
2443+ }
2444+ }
2445+ break;
2446+ case 'N':
2447+ //CTRL+N、新規作成
2448+ if(sh & CHK_CTRL) newtext();
2449+ break;
2450+ case VK_F1: //F1キー
2451+ if(sh & CHK_SHIFT) newtext();//SHIFT+F1キー 新規作成
2452+ else{
2453+ //ファイル読み込み
2454+ if(fileload()==0){ //ファイルを選択して読み込み
2455+ //読み込みを行った場合、カーソル位置を先頭に
2456+ cursor_top();
2457+ }
2458+ }
2459+ break;
2460+ case VK_F2: //F2キー
2461+ if(num==0) break;
2462+ if(sh & CHK_SHIFT) msra(); //create direct running file
2463+ else save_as(0); //ファイル名を付けて保存
2464+ break;
2465+ case VK_F3: //F3キー
2466+ if(sh & CHK_SHIFT) changewidth(); //画面幅の切り替え
2467+ break;
2468+ case VK_F4: //F4キー
2469+ if(num==0) break;
2470+ if(sh & CHK_SHIFT) run(1); //コンパイルテスト
2471+ else run(0); //コンパイル&実行
2472+ break;
2473+ case 'Z':
2474+ //CTRL+Z、アンドゥ
2475+ if(sh & CHK_CTRL) undoexec();
2476+ break;
2477+ }
2478+}
2479+void texteditor(void){
2480+//テキストエディター本体
2481+ unsigned char k1,k2,sh;
2482+ FSFILE *fp;
2483+
2484+ editormallocp=RAM;
2485+ TextBuffer=(_tbuf *)editormalloc(sizeof(_tbuf)*TBUFMAXLINE);
2486+ clipboard=editormalloc(WIDTH_XMAX*EDITWIDTHY);
2487+ filebuf=editormalloc(FILEBUFSIZE);
2488+ cwdpath=editormalloc(PATHNAMEMAX);
2489+ filenames=(unsigned char (*)[])editormalloc(MAXFILENUM*13);
2490+ undobuf=editormalloc(UNDOBUFSIZE);
2491+
2492+// TextBuffer=(_tbuf *)RAM;
2493+// clipboard=(unsigned char *)TextBuffer+sizeof(_tbuf)*TBUFMAXLINE;
2494+// filebuf=clipboard+WIDTH_XMAX*EDITWIDTHY;
2495+// cwdpath=filebuf+FILEBUFSIZE;
2496+// filenames=(unsigned char (*)[])(cwdpath+PATHNAMEMAX);
2497+// undobuf=(unsigned char *)filenames+MAXFILENUM*13;
2498+
2499+ inittextbuf(); //テキストバッファ初期化
2500+ currentfile[0]=0; //作業中ファイル名クリア
2501+ cwdpath[0]='\\'; //カレントディレクトリをルートに設定
2502+ cwdpath[1]=0;
2503+
2504+ //実行時生成一時ファイルがあった場合は読み込む
2505+ fp=FSfopen(WORKDIRFILE,"r");
2506+ if(fp!=NULL){
2507+ FSfread(cwdpath,1,PATHNAMEMAX,fp);
2508+ FSfclose(fp);
2509+ FSchdir(cwdpath);
2510+ if(loadtextfile(TEMPFILENAME)==0){
2511+ edited=1;
2512+ setcursorcolor(COLOR_ERRORTEXT);
2513+ printstr("Temporary File Loaded\n");
2514+ printstr("Current Directory is\n");
2515+ setcursorcolor(COLOR_DIR);
2516+ printstr(cwdpath);
2517+ setcursorcolor(COLOR_ERRORTEXT);
2518+ printstr("\nSave To SD Card If Necessary\n");
2519+ setcursorcolor(COLOR_NORMALTEXT);
2520+ printstr((unsigned char *)Message1); //Hit Any Key
2521+ inputchar(); //1文字入力待ち
2522+ }
2523+ else{
2524+ cwdpath[0]='\\'; //カレントディレクトリをルートに設定
2525+ cwdpath[1]=0;
2526+ }
2527+ }
2528+ cursor_top(); //カーソルをテキストバッファの先頭に移動
2529+ insertmode=1; //0:上書き、1:挿入
2530+ clipsize=0; //クリップボードクリア
2531+ blinktimer=0; //カーソル点滅タイマークリア
2532+
2533+ while(1){
2534+ redraw();//画面再描画
2535+ setcursor(cx,cy,COLOR_NORMALTEXT);
2536+ getcursorchar(); //カーソル位置の文字を退避(カーソル点滅用)
2537+ while(1){
2538+ //キー入力待ちループ
2539+ wait60thsec(1); //60分の1秒ウェイト
2540+ blinkcursorchar(); //カーソル点滅させる
2541+ k1=ps2readkey(); //キーバッファから読み込み、k1:通常文字入力の場合ASCIIコード
2542+ displaybottomline(); //画面最下行にファンクションキー機能表示
2543+ if(vkey) break; //キーが押された場合ループから抜ける
2544+ if(cursorbp1==NULL) gabagecollect1(); //1バイトガベージコレクション(範囲選択時はしない)
2545+ }
2546+ resetcursorchar(); //カーソルを元の文字表示に戻す
2547+ k2=(unsigned char)vkey; //k2:仮想キーコード
2548+ sh=vkey>>8; //sh:シフト関連キー状態
2549+ if(k2==VK_RETURN || k2==VK_SEPARATOR) k1='\n'; //Enter押下は単純に改行文字を入力とする
2550+ if(k1) normal_code_process(k1); //通常文字が入力された場合
2551+ else control_code_process(k2,sh); //制御文字が入力された場合
2552+ if(cursorbp1!=NULL && cx==cx1 && cy==cy1) cursorbp1=NULL;//選択範囲の開始と終了が重なったら範囲選択モード解除
2553+ }
2554+}
--- mips/trunk/megalopa/envspecific.h (nonexistent)
+++ mips/trunk/megalopa/envspecific.h (revision 268)
@@ -0,0 +1,90 @@
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+// Megalopa uses I/O statements/functions
9+#include "io.h"
10+
11+#define PERSISTENT_RAM_SIZE (1024*100)
12+
13+int readbuttons();
14+void scroll(int x, int y);
15+void usegraphic(int mode);
16+void videowidth(int width);
17+int lib_system(int a0, int a1 ,int v0, int a3, int g_gcolor, int g_prev_x, int g_prev_y);
18+void init_env(void);
19+void pre_run(void);
20+void post_run(void);
21+
22+// 30 or 40 characters per line for Zoea
23+#define printcomma() printstr(" "+rem10_32((unsigned int)(cursor-TVRAM)))
24+
25+// Check break key or buttons when executing BASIC code.
26+// In PS/2 mode, detect ctrl-break.
27+// In button mode, detect pushing four buttons are pushed simultaneously.
28+#define check_break() \
29+ if (g_disable_break==0) {\
30+ if (ps2keystatus[0x03]) err_break();\
31+ }
32+
33+// Megalopa specific lists of statements and functions
34+#define ADDITIONAL_STATEMENTS \
35+ "OUT " ,out_statement,\
36+ "OUT8H " ,out8h_statement,\
37+ "OUT8L " ,out8l_statement,\
38+ "OUT16 " ,out16_statement,\
39+ "PWM " ,pwm_statement,\
40+ "SERIAL " ,serial_statement,\
41+ "SERIALOUT ",serialout_statement,
42+
43+#define ADDITIONAL_INT_FUNCTIONS \
44+ "IN(" , in_function,\
45+ "IN8H(" , in8h_function,\
46+ "IN8L(" , in8l_function,\
47+ "IN16(" , in16_function,\
48+ "ANALOG(" ,analog_function,\
49+ "SERIALIN(",serialin_function,
50+
51+#define ADDITIONAL_STR_FUNCTIONS
52+#define ADDITIONAL_RESERVED_VAR_NAMES \
53+ 0x00015045, /*OUT*/ \
54+ 0x01975e81, /*OUT8H*/ \
55+ 0x01975e85, /*OUT8L*/ \
56+ 0x01975d7a, /*OUT16*/ \
57+ 0x0001015b, /*IN*/ \
58+ 0x0007dde1, /*IN8H*/ \
59+ 0x0007dde5, /*IN8L*/ \
60+ 0x0007dcda, /*IN16*/ \
61+ 0x05f0a740, /*ANALOG*/ \
62+ 0x00015596, /*PWM*/ \
63+ 0x45f58f5d, /*SERIAL*/ \
64+ 0x000163c6, /*SPI*/ \
65+ 0x47093355, /*SPIOUT*/ \
66+ 0x01fa1cff, /*SPIIN*/
67+
68+
69+#define EXTRA_MASK 0x003F
70+#define EXTRA_STEP 0x0001
71+enum extra{
72+ EXTRA_SYSTEM =EXTRA_STEP*0,
73+ EXTRA_OUT =EXTRA_STEP*1,
74+ EXTRA_OUT8H =EXTRA_STEP*2,
75+ EXTRA_OUT8L =EXTRA_STEP*3,
76+ EXTRA_OUT16 =EXTRA_STEP*4,
77+ EXTRA_IN =EXTRA_STEP*5,
78+ EXTRA_IN8H =EXTRA_STEP*6,
79+ EXTRA_IN8L =EXTRA_STEP*7,
80+ EXTRA_IN16 =EXTRA_STEP*8,
81+ EXTRA_ANALOG =EXTRA_STEP*9,
82+ EXTRA_PWM =EXTRA_STEP*10,
83+ EXTRA_SERIALOUT =EXTRA_STEP*11,
84+ EXTRA_SERIALIN =EXTRA_STEP*12,
85+ EXTRA_SERIAL =EXTRA_STEP*13,
86+ EXTRA_SPIOUT =EXTRA_STEP*14,
87+ EXTRA_SPIIN =EXTRA_STEP*15,
88+ EXTRA_SPI =EXTRA_STEP*16,
89+ // MAX 63
90+};
--- mips/trunk/megalopa/run.c (nonexistent)
+++ mips/trunk/megalopa/run.c (revision 268)
@@ -0,0 +1,152 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by K.Tanaka & Katsumi
4+ http://www.ze.em-net.ne.jp/~kenken/index.html
5+ http://hp.vector.co.jp/authors/VA016157/
6+*/
7+
8+#include <xc.h>
9+#include "api.h"
10+#include "compiler.h"
11+#include "editor.h"
12+#include "main.h"
13+
14+char* printdec(int num){
15+ char str[11];
16+ int i;
17+ if (num<0) {
18+ printchar('-');
19+ num=0-num;
20+ }
21+ for(i=10;0<i;i--){
22+ if (num==0 && i<10) break;
23+ str[i]='0'+rem10_32(num);
24+ num=div10_32(num);
25+ }
26+ for(i++;i<11;i++) {
27+ printchar(str[i]);
28+ }
29+}
30+
31+int runbasic(char *appname,int test){
32+// BASICソースのコンパイルと実行
33+// appname 実行するBASICソースファイル
34+// test 0:コンパイルと実行、0以外:コンパイルのみで終了
35+//
36+// 戻り値
37+//  0:正常終了
38+//  -1:ファイルエラー
39+//  -2:リンクエラー
40+//  1以上:コンパイルエラーの発生行(行番号ではなくファイル上の何行目か)
41+ int i;
42+ char* buff;
43+ char* err;
44+
45+ // Set grobal pointer
46+ g_gp=get_gp();
47+ // Set source positions
48+ buff=(char*)&(RAM[RAMSIZE-512]);
49+ g_source=(char*)(&buff[0]);
50+ g_srcpos=0;
51+ // Set object positions
52+ g_object=(int*)(&RAM[0]);
53+ g_objpos=0;
54+ g_objmax=g_object+(RAMSIZE-512)/4; // Buffer area excluded.
55+ // Clear object area
56+ for(i=0;i<RAMSIZE/4;i++) g_object[i]=0x00000000;
57+ // Initialize SD card file system
58+ err=init_file(buff,appname);
59+ if (err) {
60+ setcursorcolor(COLOR_ERRORTEXT);
61+ printstr("Can't Open ");
62+ printstr(appname);
63+ printchar('\n');
64+ return -1;
65+ }
66+
67+ // Initialize parameters
68+ g_pcg_font=0;
69+ g_use_graphic=0;
70+ g_graphic_area=0;
71+ clearscreen();
72+ setcursor(0,0,7);
73+ g_long_name_var_num=0;
74+ cmpdata_init();
75+
76+ // Initialize music system
77+ init_music();
78+
79+ printstr("BASIC "BASVER"\n");
80+ wait60thsec(15);
81+
82+ printstr("Compiling...");
83+
84+ // Compile the file
85+ err=compile_file();
86+ close_file();
87+ if (err) {
88+ // Compile error
89+ printstr(err);
90+ printstr("\nAround: '");
91+ for(i=0;i<5;i++){
92+ printchar(g_source[g_srcpos-2+i]);
93+ }
94+ printstr("' in line ");
95+ printdec(g_line);
96+ printstr("\n");
97+ for(i=g_srcpos;0x20<=g_source[i];i++);
98+ g_source[i]=0x00;
99+ for(i=g_srcpos;0x20<=g_source[i];i--);
100+ printstr(g_source+i);
101+ return g_fileline;
102+ }
103+
104+ // Link
105+ err=link();
106+ if (err) {
107+ // Link error
108+ printstr(err);
109+ printstr(resolve_label(g_label));
110+ return -2;
111+ }
112+
113+ // All done
114+ printstr("done\n");
115+ if(test) return 0; //コンパイルのみの場合
116+ wait60thsec(15);
117+
118+ // Initialize the other parameters
119+ // Random seed
120+ g_rnd_seed=0x92D68CA2; //2463534242
121+ // Clear variables
122+ for(i=0;i<ALLOC_BLOCK_NUM;i++){
123+ g_var_mem[i]=0;
124+ g_var_size[i]=0;
125+ }
126+ // Clear key input buffer
127+ for(i=0;i<256;i++){
128+ ps2keystatus[i]=0;
129+ }
130+ // Reset data/read.
131+ reset_dataread();
132+ // Initialize file system
133+ lib_file(FUNC_FINIT,0,0,0);
134+
135+ // Assign memory
136+ set_free_area((void*)(g_object+g_objpos),(void*)(&RAM[RAMSIZE]));
137+
138+ // Warm up environment
139+ pre_run();
140+
141+ // Execute program
142+ // Start program from the beginning of RAM.
143+ // Work area (used for A-Z values) is next to the object code area.
144+ start_program((void*)(&(RAM[0])),(void*)(&g_var_mem[0]));
145+ printstr("\nOK\n");
146+
147+ // Cool down environment
148+ post_run();
149+ lib_file(FUNC_FINIT,0,0,0);
150+
151+ return 0;
152+}
--- mips/trunk/megalopa/debug.c (nonexistent)
+++ mips/trunk/megalopa/debug.c (revision 268)
@@ -0,0 +1,245 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by K.Tanaka & Katsumi
4+ http://www.ze.em-net.ne.jp/~kenken/index.html
5+ http://hp.vector.co.jp/authors/VA016157/
6+*/
7+
8+#ifdef __DEBUG
9+
10+#include <xc.h>
11+#include "api.h"
12+#include "main.h"
13+#include "compiler.h"
14+
15+/*
16+ Enable following line when debugging binary object.
17+*/
18+//#include "debugdump.h"
19+
20+
21+// Pseudo reading config setting for debug mode
22+unsigned int g_DEVCFG1=0xFF7F4DDB;
23+
24+// Construct jump assembly in boot area.
25+const unsigned int _debug_boot[] __attribute__((address(0xBFC00000))) ={
26+ 0x0B401C00,// j 0x9d007000
27+ 0x00000000,// nop
28+};
29+
30+// Use DEBUG.HEX as file name of this program.
31+const unsigned char _debug_filename[] __attribute__((address(FILENAME_FLASH_ADDRESS))) ="DEBUG.HEX";
32+
33+static const char initext[];
34+static const char bastext[];
35+
36+static char* readtext;
37+static int filepos;
38+
39+/*
40+ Debug dump
41+ In debugdump.h:
42+ __DEBUGDUMP is defined.
43+ __DEBUGDUMP_FREEAREA is defined as start address of free area (1st argument of set_free_area() function)
44+ const unsigned char dump[] is initialized.
45+*/
46+#ifdef __DEBUGDUMP
47+int debugDump(){
48+ int i;
49+ for(i=0;i<sizeof dump;i++){
50+ RAM[i]=dump[i];
51+ }
52+
53+ g_objpos=(__DEBUGDUMP_FREEAREA-(unsigned int)g_object)/4;
54+
55+ // Initialize parameters
56+ g_pcg_font=0;
57+ g_use_graphic=0;
58+ g_graphic_area=0;
59+ clearscreen();
60+ setcursor(0,0,7);
61+
62+ printstr("BASIC "BASVER"\n");
63+ wait60thsec(15);
64+
65+ printstr("Compiling...");
66+
67+ // Initialize the other parameters
68+ // Random seed
69+ g_rnd_seed=0x92D68CA2; //2463534242
70+ // Clear variables
71+ for(i=0;i<ALLOC_BLOCK_NUM;i++){
72+ g_var_mem[i]=0;
73+ g_var_size[i]=0;
74+ }
75+ // Clear key input buffer
76+ for(i=0;i<256;i++){
77+ ps2keystatus[i]=0;
78+ }
79+ // Reset data/read.
80+ reset_dataread();
81+
82+ // Assign memory
83+ set_free_area((void*)(g_object+g_objpos),(void*)(&RAM[RAMSIZE]));
84+ // Execute program
85+ // Start program from the beginning of RAM.
86+ // Work area (used for A-Z values) is next to the object code area.
87+ start_program((void*)(&(RAM[0])),(void*)(&g_var_mem[0]));
88+ printstr("\nOK\n");
89+ g_use_graphic=0;
90+
91+ return 1;
92+}
93+#else
94+int debugDump(){
95+ return 0;
96+}
97+#endif
98+
99+/*
100+ Override libsdfsio functions.
101+ Here, don't use SD card, but the vertual files
102+ (initext[] and bastext[]) are used.
103+*/
104+
105+FSFILE fsfile;
106+
107+size_t FSfread(void *ptr, size_t size, size_t n, FSFILE *stream){
108+ char b;
109+ size_t ret=0;
110+ if (!readtext) return 0;
111+ while(b=readtext[filepos]){
112+ filepos++;
113+ ((char*)ptr)[ret]=b;
114+ ret++;
115+ if (n<=ret) break;
116+ }
117+ return ret;
118+}
119+FSFILE* FSfopen(const char * fileName, const char *mode){
120+ int i;
121+ for(i=0;i<13;i++){
122+ if (fileName[i]=='.') break;
123+ }
124+ if (i==13) {
125+ // Unknown file name
126+ // Force BAS file
127+ readtext=(char*)&bastext[0];
128+ } else if (fileName[i+1]=='I' && fileName[i+2]=='N' && fileName[i+3]=='I') {
129+ // INI file
130+ readtext=(char*)&initext[0];
131+ } else if (fileName[i+1]=='B' && fileName[i+2]=='A' && fileName[i+3]=='S') {
132+ // BAS file
133+ readtext=(char*)&bastext[0];
134+ // Try debugDump.
135+ if (debugDump()) return 0;
136+ } else {
137+ readtext=0;
138+ return 0;
139+ }
140+ filepos=0;
141+ return &fsfile;
142+}
143+int FSfeof( FSFILE * stream ){
144+ return readtext[filepos]?1:0;
145+}
146+int FSfclose(FSFILE *fo){
147+ return 0;
148+}
149+int FSInit(void){
150+ return 1;
151+}
152+int FSremove (const char * fileName){
153+ return 0;
154+}
155+size_t FSfwrite(const void *ptr, size_t size, size_t n, FSFILE *stream){
156+ return 0;
157+}
158+
159+int FindFirst (const char * fileName, unsigned int attr, SearchRec * rec){
160+ return 0;
161+}
162+int FindNext (SearchRec * rec){
163+ return 0;
164+}
165+int FSmkdir (char * path){
166+ return 0;
167+}
168+char * FSgetcwd (char * path, int numchars){
169+ return 0;
170+}
171+int FSchdir (char * path){
172+ return 0;
173+}
174+long FSftell (FSFILE * fo){
175+ return 0;
176+}
177+int FSfseek(FSFILE *stream, long offset, int whence){
178+ return 0;
179+}
180+/*
181+ ps2init() is not called.
182+ Instead, not_ps2init_but_init_Timer1() is called.
183+ Timer1 is used to update drawcount and drawing gloval variables.
184+*/
185+
186+int not_ps2init_but_init_Timer1(){
187+ PR1=0x0FFF;
188+ TMR1=0;
189+ IFS0bits.T1IF=0;
190+ T1CON=0x8000;
191+ // Timer1 interrupt: priority 4
192+ IPC1bits.T1IP=4;
193+ IPC1bits.T1IS=0;
194+ IEC0bits.T1IE=1;
195+
196+ return 0;
197+}
198+
199+#pragma interrupt timer1Int IPL4SOFT vector 4
200+
201+void timer1Int(){
202+ IFS0bits.T1IF=0;
203+ if (drawing) {
204+ drawing=0;
205+ drawcount++;
206+ } else {
207+ drawing=1;
208+ }
209+}
210+
211+/*
212+ initext[] and bastext[] are vertual files
213+ as "MACHIKAN.INI" and "DEBUG.BAS".
214+*/
215+
216+
217+static const char initext[]=
218+"#PRINT\n"
219+"#PRINT\n";
220+
221+
222+static const char bastext[]=
223+"CLS\n"
224+"print NOT(0);IN(0)\n"
225+"\n";
226+
227+/*
228+ Test function for constructing assemblies from C codes.
229+*/
230+
231+int _debug_test(int a0, int a1, int a2, int a3, int param4, int param5){
232+// if (a0<0xa0008192) return 0xa0000000;
233+ asm volatile("lw $sp,18($fp)");
234+ asm volatile("addiu $sp,$sp,2044");
235+ return a2+a3;
236+}
237+
238+/*
239+ Break point used for debugging object code.
240+
241+g_object[g_objpos++]=0x0000000d;// break 0x0
242+
243+*/
244+
245+#endif // __DEBUG
--- mips/trunk/megalopa/io.h (nonexistent)
+++ mips/trunk/megalopa/io.h (revision 268)
@@ -0,0 +1,34 @@
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+void lib_out(int pos, int val);
9+void lib_out8h(int val);
10+void lib_out8l(int val);
11+int lib_out16(int val);
12+int lib_in(int pos);
13+int lib_in8h();
14+int lib_in8l();
15+int lib_in16();
16+int lib_analog(int pos);
17+void lib_pwm(int duty, int freq, int num);
18+void lib_serial(int baud, int parity, int bsize);
19+void lib_serialout(int data);
20+int lib_serialin(int mode);
21+
22+char* out_statement();
23+char* out8h_statement();
24+char* out8l_statement();
25+char* out16_statement();
26+char* pwm_statement();
27+char* serial_statement();
28+char* serialout_statement();
29+char* in_function();
30+char* in8h_function();
31+char* in8l_function();
32+char* in16_function();
33+char* analog_function();
34+char* serialin_function();
--- mips/trunk/megalopa/memory.c (nonexistent)
+++ mips/trunk/megalopa/memory.c (revision 268)
@@ -0,0 +1,184 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by Katsumi.
4+ http://hp.vector.co.jp/authors/VA016157/
5+ kmorimatsu@users.sourceforge.jp
6+*/
7+
8+#include "compiler.h"
9+
10+/*
11+ ALLOC_VAR_NUM: # of variables used for allocation of memory (string/dimension).
12+ 0 is for A, 1 is for B, ... , and 25 is for Z.
13+ This number also includes temporary area used for string construction etc.
14+ Temporary area is cleared every line of BASIC code in alloc_memory().
15+ ALLOC_BLOCK_NUM: # of blocks that can be used for memory allocation.
16+ This # also includes the ones for ALLOC_VAR_NUM.
17+ After ALLOC_VAR_NUM area, dedicated memory area and permanent area follows.
18+ Currently, only PCG is used for permanent pourpose.
19+ 10 permanant blocks can be used.
20+ Therefore, ALLOC_VAR_NUM+11 == ALLOC_BLOCK_NUM
21+ ALLOC_PERM_BLOCK: Start # of permanent blocks.
22+ The blocks after this number is permanently stored.
23+ Therefore, it must be released when it's not used any more.
24+*/
25+
26+void set_free_area(void* begin, void* end){
27+ int i;
28+ for(i=0;i<ALLOC_BLOCK_NUM;i++){
29+ g_var_size[i]=0;
30+ }
31+ g_heap_mem=(int*)begin;
32+ g_max_mem=(int)((end-begin)/4);
33+}
34+
35+void* calloc_memory(int size, int var_num){
36+ int i;
37+ void* ret;
38+ // Allocate memory
39+ ret=alloc_memory(size,var_num);
40+ // Fill zero in allocated memory
41+ for(i=0;i<size;i++){
42+ ((int*)ret)[i]=0;
43+ }
44+ // return pointer to allocated memory
45+ return ret;
46+}
47+void* alloc_memory(int size, int var_num){
48+ // Remove temporary blocks once a line.
49+ asm volatile("nop");
50+ asm volatile("bltz $s6,_alloc_memory_main"); // Skip if $s6<0
51+ // Following code will be activated after setting $s6 register
52+ // every line and after label statement.
53+ asm volatile("lui $v0,0x8000");
54+ asm volatile("or $s6,$v0,$s6"); // $s6=0x80000000|$s6;
55+ // Remove all temporary blocks
56+ // Note that g_var_size is short integer.
57+ // Note that ALLOC_VAR_NUM is used here (but not ALLOC_BLOC_NUM)
58+ // for(i=26;i<ALLOC_VAR_NUM;i++)g_var_size[i]=0;
59+ asm volatile("addiu $v0,$zero,%0"::"n"((ALLOC_VAR_NUM-26)/2)); // $v0=(ALLOC_VAR_NUM-26)/2
60+ asm volatile("la $v1,%0"::"i"(&g_var_size[0])); // $v1=g_var_size
61+ asm volatile("loop:");
62+ asm volatile("sw $zero,(26*2)($v1)"); // $v1[26]=0, $v1[27]=0
63+ asm volatile("addiu $v0,$v0,-1"); // $v0--
64+ asm volatile("addiu $v1,$v1,4"); // $v1+=2
65+ asm volatile("bne $v0,$zero,loop"); // loop if 0<$v0
66+ asm volatile("b _alloc_memory_main");
67+}
68+void* _alloc_memory_main(int size, int var_num){
69+ int i,j,candidate;
70+ // Assign temp var number
71+ if (var_num<0) {
72+ // Use ALLOC_VAR_NUM here but not ALLOC_BLOCK_NUM
73+ for(i=26;i<ALLOC_VAR_NUM;i++){
74+ if (g_var_size[i]==0) {
75+ var_num=i;
76+ break;
77+ }
78+ }
79+ if (var_num<0) {
80+ err_str_complex();
81+ return 0;
82+ }
83+ }
84+ // Clear var to be assigned.
85+ g_var_size[var_num]=0;
86+ g_var_pointer[var_num]=0;
87+ while(1){
88+ // Try the block after last block
89+ candidate=0;
90+ for(i=0;i<ALLOC_BLOCK_NUM;i++){
91+ if (g_var_size[i]==0) continue;
92+ if (candidate<=g_var_pointer[i]) {
93+ candidate=g_var_pointer[i]+g_var_size[i];
94+ }
95+ }
96+ if (candidate+size<=g_max_mem) break;
97+ // Check between blocks
98+ // Note that there is at least one block with zero pointer and zero size (see above).
99+ for(i=0;i<ALLOC_BLOCK_NUM;i++){
100+ // Candidate is after this block.
101+ candidate=g_var_pointer[i]+g_var_size[i];
102+ // Check if there is an overlap.
103+ for(j=0;j<ALLOC_BLOCK_NUM;j++){
104+ if (g_var_size[j]==0) continue;
105+ if (candidate+size<=g_var_pointer[j]) continue;
106+ if (g_var_pointer[j]+g_var_size[j]<=candidate) continue;
107+ // This block overlaps with the candidate
108+ candidate=-1;
109+ break;
110+ }
111+ if (0<=candidate && candidate+size<=g_max_mem) {
112+ // Available block found
113+ break;
114+ } else {
115+ candidate=-1;
116+ }
117+ }
118+ if (0<=candidate) break;
119+ // New memory block cannot be allocated.
120+ err_no_mem();
121+ return 0;
122+ }
123+ // Available block found.
124+ g_var_pointer[var_num]=candidate;
125+ g_var_size[var_num]=size;
126+ g_var_mem[var_num]=(int)(&(g_heap_mem[candidate]));
127+ return (void*)g_var_mem[var_num];
128+}
129+
130+void free_temp_str(char* str){
131+ int i,pointer;
132+ if (!str) return;
133+ pointer=(int)str-(int)g_heap_mem;
134+ pointer>>=2;
135+ for(i=0;i<ALLOC_BLOCK_NUM;i++){
136+ if (g_var_pointer[i]==pointer) {
137+ g_var_size[i]=0;
138+ break;
139+ }
140+ }
141+}
142+
143+void move_to_perm_block(int var_num){
144+ int i;
145+ // Find available permanent block
146+ for (i=ALLOC_PERM_BLOCK;i<ALLOC_BLOCK_NUM;i++){
147+ if (g_var_size[i]==0) break;
148+ }
149+ if (ALLOC_BLOCK_NUM<=i) err_no_block(); // Not found
150+ // Available block found.
151+ // Copy value from variable.
152+ g_var_size[i]=g_var_size[var_num];
153+ g_var_pointer[i]=g_var_pointer[var_num];
154+ g_var_mem[i]=g_var_mem[var_num];
155+ // Clear variable
156+ g_var_size[var_num]=0;
157+ g_var_mem[var_num]=0;
158+}
159+
160+void move_from_perm_block(int var_num){
161+ int i,pointer;
162+ pointer=(int)g_var_mem[var_num]-(int)g_heap_mem;
163+ pointer>>=2;
164+ // Find stored block
165+ for (i=ALLOC_PERM_BLOCK;i<ALLOC_BLOCK_NUM;i++){
166+ if (0<g_var_size[i] && g_var_pointer[i]==pointer) break;
167+ }
168+ if (ALLOC_BLOCK_NUM<=i) err_unknown(); // Not found
169+ // Stored block found.
170+ // Replace pointer
171+ g_var_size[var_num]=g_var_size[i];
172+ g_var_pointer[var_num]=g_var_pointer[i];
173+ // Clear block
174+ g_var_size[i]=0;
175+}
176+
177+int get_permanent_var_num(){
178+ int i;
179+ for (i=ALLOC_PERM_BLOCK;i<ALLOC_BLOCK_NUM;i++) {
180+ if (g_var_size[i]==0) return i;
181+ }
182+ err_no_block();
183+ return 0;
184+}
--- mips/trunk/megalopa/varname.c (nonexistent)
+++ mips/trunk/megalopa/varname.c (revision 268)
@@ -0,0 +1,228 @@
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+ static const int reserved_var_names[];
12+ This dimension contains var name integers of reserved var names.
13+ To make following structure, execute "reservednames.js" in Windows.
14+*/
15+
16+static const int reserved_var_names[]={
17+ 0x000106b8, //ABS
18+ 0x0001f67c, //ACOS
19+ 0x0002414c, //ARGS
20+ 0x0001090c, //ASC
21+ 0x0002469f, //ASIN
22+ 0x00024a8f, //ATAN
23+ 0x002f7c1e, //ATAN2
24+ 0x0047c31c, //BREAK
25+ 0x00575afe, //CDATA
26+ 0x00036c3d, //CEIL
27+ 0x000111af, //CHR
28+ 0x0cb1b682, //CIRCLE
29+ 0x005d1ea3, //CLEAR
30+ 0x00011240, //CLS
31+ 0x005f66cb, //COLOR
32+ 0x000112ac, //COS
33+ 0x0003a041, //COSH
34+ 0x00616415, //CREAD
35+ 0x0de593fb, //CURSOR
36+ 0x00040fbe, //DATA
37+ 0x00011644, //DEC
38+ 0x000116de, //DIM
39+ 0x000100a8, //DO
40+ 0x0004fd8e, //ELSE
41+ 0x1434a177, //ELSEIF
42+ 0x00011c99, //END
43+ 0x0091c927, //ENDIF
44+ 0x00053854, //EXEC
45+ 0x00011e0d, //EXP
46+ 0x000579c8, //FABS
47+ 0x16e3d4be, //FCLOSE
48+ 0x00058fcf, //FEOF
49+ 0x00059895, //FGET
50+ 0x00a67500, //FGETC
51+ 0x0005a3a2, //FILE
52+ 0x177f0ca5, //FINPUT
53+ 0x0005b1df, //FLEN
54+ 0x00aa3445, //FLOAT
55+ 0x00aa363b, //FLOOR
56+ 0x0005b84d, //FMOD
57+ 0x00ac5c9f, //FOPEN
58+ 0x000121db, //FOR
59+ 0x18352839, //FPRINT
60+ 0x0005c865, //FPUT
61+ 0x00ad2e40, //FPUTC
62+ 0x00aefdec, //FSEEK
63+ 0x00063b90, //GCLS
64+ 0x1a808bcb, //GCOLOR
65+ 0x00c60f03, //GOSUB
66+ 0x0006796c, //GOTO
67+ 0x1bcfcc39, //GPRINT
68+ 0x00012a99, //HEX
69+ 0x00010153, //IF
70+ 0x00f8701a, //INKEY
71+ 0x00f88ba5, //INPUT
72+ 0x000130e9, //INT
73+ 0x00092084, //KEYS
74+ 0x013be43d, //LABEL
75+ 0x00013ecf, //LEN
76+ 0x00013ed5, //LET
77+ 0x0009e96a, //LINE
78+ 0x00014030, //LOG
79+ 0x0145f324, //LOG10
80+ 0x000a07f9, //LOOP
81+ 0x000abca3, //MODF
82+ 0x016418d4, //MUSIC
83+ 0x000b4321, //NEXT
84+ 0x00014a5d, //NOT
85+ 0x000152c0, //PCG
86+ 0x000cacec, //PEEK
87+ 0x00010252, //PI
88+ 0x01ac8479, //POINT
89+ 0x000ce05e, //POKE
90+ 0x00015480, //POW
91+ 0x01aea739, //PRINT
92+ 0x000cf3d5, //PSET
93+ 0x3cc0fe21, //PUTBMP
94+ 0x000e18d5, //READ
95+ 0x00015d2e, //REM
96+ 0x425c9703, //RETURN
97+ 0x00015e69, //RND
98+ 0x45c26d49, //SCROLL
99+ 0x00016287, //SGN
100+ 0x000162cf, //SIN
101+ 0x000ee52d, //SINH
102+ 0x01f9a429, //SOUND
103+ 0x000f0e49, //SQRT
104+ 0x47f711de, //SYSTEM
105+ 0x000166bf, //TAN
106+ 0x000f72ed, //TANH
107+ 0x02182fee, //TVRAM
108+ 0x022c2a2d, //UNTIL
109+ 0x4e8887d0, //USEPCG
110+ 0x4e88a5f3, //USEVAR
111+ 0x000170dd, //VAL
112+ 0x000170e3, //VAR
113+ 0x00119505, //WAIT
114+ 0x0011a9e9, //WEND
115+ 0x025aef62, //WHILE
116+ 0x025b8d75, //WIDTH
117+ // Additional names follow
118+ ADDITIONAL_RESERVED_VAR_NAMES
119+};
120+
121+/*
122+ check_var_name();
123+ This function reads the current position of source code and check if
124+ it contains valid var name, the function returns 0 or plus value.
125+ If not, it returns -1;
126+*/
127+
128+int check_var_name(){
129+ char b1;
130+ int j;
131+ int i=0;
132+ int prevpos=g_srcpos;
133+ next_position();
134+ b1=g_source[g_srcpos];
135+ if (b1<'A' || 'Z'<b1) return -1;
136+ do {
137+ // First character must be A-Z
138+ // From second, A-Z and 0-9 can be used.
139+ i*=36;
140+ if ('0'<=b1 && b1<='9') {
141+ i+=b1-'0';
142+ } else if (g_srcpos==prevpos) {
143+ // First character must be A-Z.
144+ // Subtract 9, resulting 1-26 but not 10-35.
145+ // This subtraction is required to maintain
146+ // final number being <0x80000000.
147+ i+=b1-'A'+1;
148+ } else {
149+ i+=b1-'A'+10;
150+ }
151+ g_srcpos++;
152+ b1=g_source[g_srcpos];
153+ } while ('0'<= b1 && b1<='9' || 'A'<=b1 && b1<='Z');
154+ // Length of the label must be between 2 and 6.
155+ if (g_srcpos-prevpos<2) {
156+ // One letter var name, A-Z
157+ return i-1;
158+ }
159+ if (6<g_srcpos-prevpos) {
160+ // Too long. This is not var name.
161+ g_srcpos=prevpos;
162+ return -1;
163+ }
164+ i+=65536;
165+ // Check if this is reserved var name.
166+ for(j=0;j<sizeof reserved_var_names/sizeof reserved_var_names[0];j++){
167+ if (reserved_var_names[j]==i) {
168+ // This var name is reserved as used for function or statement.
169+ g_srcpos=prevpos;
170+ return -1;
171+ }
172+ }
173+ // Reserved var names table was checked. This must be a long var name.
174+ return i;
175+}
176+
177+/*
178+ int get_var_number();
179+ This function returns variable number that can be used as the index of $s8
180+*/
181+
182+int get_var_number(){
183+ int i;
184+ // This must be a short or long var name.
185+ i=check_var_name();
186+ if (i<0) return -1;
187+ // If it is a short name, immediately return.
188+ if (i<26) return i;
189+ // Search long var names registered by USEVAR statement.
190+ // If found, returns the value that can be used as the index of $s8
191+ i=search_var_name(i);
192+ if (i<0) return -1;
193+ // This var name is defined by USEVAR statement.
194+ return i+ALLOC_LNV_BLOCK;
195+
196+}
197+
198+/*
199+ int search_var_name(int nameint);
200+ This function searchs registered long var name in compile data table.
201+ If not found, this function returns -1.
202+ If found, it retunrs var number, beginning 0.
203+*/
204+
205+int search_var_name(int nameint){
206+ int* cmpdata;
207+ cmpdata_reset();
208+ while(cmpdata=cmpdata_find(CMPDATA_USEVAR)){
209+ if (cmpdata[1]==nameint) return cmpdata[0]&0x0000ffff;
210+ }
211+ return -1;
212+}
213+
214+/*
215+ char* register_var_name(int nameint);
216+ This function is called when compiler detects "USEVAR" statement.
217+ It registers the long file name in compile data table.
218+*/
219+
220+char* register_var_name(int nameint){
221+ // Check if registered before. If did, cause error.
222+ if (search_var_name(nameint)!=-1) return ERR_INVALID_VAR_NAME;
223+ // Number of long var name is restricted
224+ if (ALLOC_LNV_NUM<=g_long_name_var_num) return ERR_INVALID_VAR_NAME;
225+ // Register var name as a compile data
226+ g_temp=nameint;
227+ return cmpdata_insert(CMPDATA_USEVAR,g_long_name_var_num++,&g_temp,1);
228+}
--- mips/trunk/megalopa/editor.h (nonexistent)
+++ mips/trunk/megalopa/editor.h (revision 268)
@@ -0,0 +1,43 @@
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+#define TBUFMAXLINE 181 //テキストバッファ数
9+
10+#define TBUFSIZE 200 //テキストバッファ1つのサイズ
11+#define TBUFMAXSIZE (TBUFSIZE*(TBUFMAXLINE-1)) //最大バッファ容量(バッファ1行分空ける)
12+//#define EDITWIDTHX 36 //エディタ画面横幅
13+#define EDITWIDTHY 26 //エディタ画面縦幅
14+#define COLOR_NORMALTEXT 7 //通常テキスト色
15+#define COLOR_ERRORTEXT 4 //エラーメッセージテキスト色
16+#define COLOR_AREASELECTTEXT 4 //範囲選択テキスト色
17+#define COLOR_BOTTOMLINE 5 //画面最下行の色
18+#define COLOR_DIR 6 //ディレクトリ名表示の色
19+#define COLOR_INV 128 //モノクロモード時の反転
20+#define FILEBUFSIZE 256 //ファイルアクセス用バッファサイズ
21+#define MAXFILENUM 200 //利用可能ファイル最大数
22+#define PATHNAMEMAX 128 //ワーキングディレクトリパス名の最大値
23+#define UNDOBUFSIZE 2048 //アンドゥ用バッファサイズ
24+
25+#define ERR_FILETOOBIG -1
26+#define ERR_CANTFILEOPEN -2
27+#define ERR_CANTWRITEFILE -3
28+
29+#define TEMPFILENAME "~TEMP.BAS" //実行時ソース保存ファイル名
30+#define WORKDIRFILE "~WORKDIR.TMP" //実行時パス保存ファイル名
31+
32+#define UNDO_INSERT 1
33+#define UNDO_OVERWRITE 2
34+#define UNDO_DELETE 3
35+#define UNDO_BACKSPACE 4
36+#define UNDO_CONTINS 5
37+#define UNDO_CONTDEL 6
38+
39+void texteditor(void); //テキストエディタ本体
40+int runbasic(char *s,int test); //コンパイルして実行
41+extern unsigned char tempfile[13];
42+void wait60thsec(unsigned short n);
43+
--- mips/trunk/megalopa/keyinput.c (nonexistent)
+++ mips/trunk/megalopa/keyinput.c (revision 268)
@@ -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 "lib_video_megalopa.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/trunk/megalopa/exception.c (nonexistent)
+++ mips/trunk/megalopa/exception.c (revision 268)
@@ -0,0 +1,159 @@
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+/*
14+ Enable following line if memory dump is needed when exception occurs.
15+*/
16+
17+//#define DUMPFILE "~~MEMORY.DMP"
18+
19+#ifdef DUMPFILE
20+void dumpMemory(){
21+ unsigned int i;
22+ FSFILE *fp;
23+ printstr("\n"DUMPFILE" ");
24+ if(FSInit()==FALSE){
25+ printstr("cannot be created.\n");
26+ return;
27+ }
28+ fp=FSfopen(DUMPFILE,"w");
29+ if(fp==NULL) {
30+ printstr("not saved.\n");
31+ return;
32+ }
33+ for(i=0;i<PERSISTENT_RAM_SIZE;i+=512){
34+ if (FSfwrite(&RAM[i],1,512,fp)<512) break;
35+ }
36+ FSfclose(fp);
37+ printstr("saved.\n");
38+}
39+#else
40+void dumpMemory(){}
41+#endif //ifdef DUMPFILE
42+
43+void _general_exception_handler (void){
44+ int i;
45+ // $v1 is g_ex_data
46+ asm volatile("la $v1,%0"::"i"(&g_ex_data[0]));
47+ // Prepare proper stack area before SoftReset
48+ asm volatile("addiu $sp,$v1,0xfff0");
49+ // g_ex_data[2]=$s6
50+ asm volatile("sw $s6,8($v1)");
51+ // g_ex_data[3]=Cause
52+ asm volatile("mfc0 $v0,$13");
53+ asm volatile("sw $v0,12($v1)");
54+ // g_ex_data[4]=EPC
55+ asm volatile("mfc0 $v0,$14");
56+ asm volatile("sw $v0,16($v1)");
57+ // Exception occured
58+ g_ex_data[0]=1;
59+ // g_s6
60+ g_ex_data[1]=g_s6;
61+ // Clear 2 MLB bits of EPC
62+ g_ex_data[4]&=0xfffffffc;
63+ // If EPC is within RAM, store data in exception area.
64+ if ((int)(&RAM[0])<=g_ex_data[4] && g_ex_data[4] <(int)(&RAM[RAMSIZE])) {
65+ // g_ex_data[5] - g_ex_data[12]: assembly
66+ for(i=-3;i<=3;i++){
67+ g_ex_data[i+8]=((int*)g_ex_data[4])[i];
68+ }
69+ }
70+ // Wait until all buttons are released and reset MachiKania.
71+ #ifdef __DEBUG
72+ asm volatile("j 0xBFC00000");
73+ #else
74+ for(i=0;i<100000;i++){
75+ if((readbuttons()&(KEYUP|KEYDOWN|KEYLEFT|KEYRIGHT|KEYSTART|KEYFIRE))
76+ !=(KEYUP|KEYDOWN|KEYLEFT|KEYRIGHT|KEYSTART|KEYFIRE)) i=0;
77+ }
78+ asm volatile("j SoftReset");
79+ #endif
80+}
81+
82+void blue_screen(void){
83+ int i,j,s6,s6g;
84+ unsigned int* opos;
85+ if (RCONbits.POR || RCONbits.EXTR) {
86+ // After power on or reset. Reset flags and return.
87+ RCONbits.POR=0;
88+ RCONbits.EXTR=0;
89+ for(i=0;i<RAMSIZE;i++){
90+ // Reset all RAM area including g_ex_data[]
91+ RAM[i]=0;
92+ }
93+ return;
94+ } else if (g_ex_data[0]==0) {
95+ // No exception found.
96+ return;
97+ }
98+ // Exception occured before SoftReset().
99+ // Prepare data
100+ s6=g_ex_data[2];
101+ s6g=g_ex_data[1];
102+ s6=s6&0x7fffffff;
103+ s6g=s6g&0x7fffffff;
104+ opos=(int*)g_ex_data[4];
105+ //set_bgcolor(255,0,0);
106+ printstr("STOP");
107+ printstr("\nException at ");
108+ printhex32(g_ex_data[4]);
109+ printstr("\n Cause: ");
110+ printhex32(g_ex_data[3]);
111+ printstr("\n ");
112+ switch((g_ex_data[3]>>2)&0x1f){
113+ case 0: printstr("(Interrupt)"); break;
114+ case 1: printstr("(TLB modification)"); break;
115+ case 2: printstr("(TLB load/fetch)"); break;
116+ case 3: printstr("(TLB store)"); break;
117+ case 4: printstr("(Address load/fetch error )"); break;
118+ case 5: printstr("(Address store error)"); break;
119+ case 6: printstr("(Bus fetch error)"); break;
120+ case 7: printstr("(Bus load/store error)"); break;
121+ case 8: printstr("(Syscall)"); break;
122+ case 9: printstr("(Breakpoint)"); break;
123+ case 10: printstr("(Reserved instruction)"); break;
124+ case 11: printstr("(Coprocessor Unusable)"); break;
125+ case 12: printstr("(Integer Overflow)"); break;
126+ case 13: printstr("(Trap)"); break;
127+ case 23: printstr("(Reference to Watch address)"); break;
128+ case 24: printstr("(Machine check)"); break;
129+ default: printstr("(Unknown)"); break;
130+ }
131+ printstr("\n s6: ");
132+ printstr(resolve_label(s6));
133+ printstr("\n g_s6: ");
134+ printstr(resolve_label(s6g));
135+ printstr("\n");
136+ printstr("Reset MachiKania to contine.\n\n");
137+ // Show code where the exception happened.
138+ for(i=-3;i<=3;i++){
139+ printstr("\n ");
140+ printhex32((unsigned int)&opos[i]);
141+ printstr(" ");
142+ if ((unsigned int)&RAM[0]<=(unsigned int)&opos[i] && (unsigned int)&opos[i]<(unsigned int)&RAM[RAMSIZE]) {
143+ // Exception in RAM[RAMSIZE] area
144+ printhex32(g_ex_data[i+8]);
145+ } else if ( 0xA0000000<=(unsigned int)&opos[i] && (unsigned int)&opos[i]<0xA0000000+PIC32MX_RAMSIZE
146+ || 0x9D000000<=(unsigned int)&opos[i] && (unsigned int)&opos[i]<=0x9D000000+PIC32MX_FLASHSIZE) {
147+ // Exception in outside RAM[RAMSIZE] or flash area
148+ printhex32(opos[i]);
149+ } else {
150+ printstr("********");
151+ }
152+ }
153+ printstr("\n");
154+
155+#ifndef __DEBUG
156+ dumpMemory();
157+#endif
158+ while(1) asm("wait");
159+}
--- mips/trunk/megalopa/globalvars.c (nonexistent)
+++ mips/trunk/megalopa/globalvars.c (revision 268)
@@ -0,0 +1,79 @@
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+unsigned 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+
72+// Parameter-containing block used for library
73+int* g_libparams;
74+
75+// Number of long name variables
76+int g_long_name_var_num;
77+
78+// General purpose integer used for asigning value with pointer
79+int g_temp;
--- mips/trunk/megalopa/ps2keyboard.h (nonexistent)
+++ mips/trunk/megalopa/ps2keyboard.h (revision 268)
@@ -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+// Macros for dummy functions
172+#define ps2mode() (0)
173+#define buttonmode() (0)
174+#define inPS2MODE() (1)
--- mips/trunk/megalopa/api.h (nonexistent)
+++ mips/trunk/megalopa/api.h (revision 268)
@@ -0,0 +1,42 @@
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 "lib_video_megalopa.h"
36+#include "sdfsio370f.h"
37+#include "ps2keyboard.h"
38+#include "debug.h"
39+
40+// Palette is shared between text and graphic
41+#define g_set_palette set_palette
42+
--- mips/trunk/megalopa/cmpdata.c (nonexistent)
+++ mips/trunk/megalopa/cmpdata.c (revision 268)
@@ -0,0 +1,86 @@
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+ This file provide functions for handling data used when compiling.
12+ The data is inserted between g_objmax and file cache.
13+ Data format (32 bit):
14+ MSB LSB
15+ +----+----+--------+
16+ |type|len | data16 |
17+ +----+----+--------+
18+ where,
19+ type: data type number (unsigned char)
20+ len: length of data area in number of words (unsigned char)
21+ data16: general 16 bit data (short)
22+*/
23+
24+#define g_cmpdata g_objmax
25+
26+static int* g_cmpdata_end;
27+static int* g_cmpdata_point;
28+
29+/*
30+ Initialize routine must be called when starting compiler.
31+*/
32+void cmpdata_init(){
33+ g_cmpdata_end=g_objmax;
34+ g_cmpdata_point=g_objmax;
35+}
36+
37+/*
38+ Function to insert a data. The data must be defined by a pointer to int array.
39+ unsigned char type: Data type number (0-255)
40+ short data16: 16 bit data. If not required, set 0.
41+ int* data: Pointer to data array. If not requird, set 0.
42+ unsigned char num: Length of above data array. If not required, set 0.
43+*/
44+char* cmpdata_insert(unsigned char type, short data16, int* data, unsigned char num){
45+ unsigned char i;
46+ g_cmpdata-=num+1;
47+ if (g_cmpdata<g_object+g_objpos) return ERR_NE_BINARY;
48+ g_cmpdata[0]=(type<<24)|(num+1)<<16|data16;
49+ for(i=0;i<num;i++){
50+ g_cmpdata[i+1]=data[i];
51+ }
52+ return 0;
53+}
54+
55+/*
56+ Reset data point. Next search will be from the beginning.
57+*/
58+
59+void cmpdata_reset(){
60+ g_cmpdata_point=g_cmpdata;
61+}
62+
63+/*
64+ Find the next record with defined type. Return the pointer to the record.
65+*/
66+int* cmpdata_find(unsigned char type){
67+ int* ret;
68+ while(g_cmpdata_point<g_cmpdata_end){
69+ // Remember return value
70+ ret=g_cmpdata_point;
71+ // Move the point to next
72+ g_cmpdata_point+=(ret[0]&0x00ff0000)>>16;
73+ // Check if type is the same. If the same, return.
74+ if ((ret[0]>>24)==type) return ret;
75+ }
76+ return 0;
77+}
78+
79+/*
80+ Find the record from beginning.
81+*/
82+
83+int* cmpdata_findfirst(unsigned char type){
84+ cmpdata_reset();
85+ return cmpdata_find(type);
86+}
--- mips/trunk/megalopa/float.c (nonexistent)
+++ mips/trunk/megalopa/float.c (revision 268)
@@ -0,0 +1,143 @@
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(1);
30+ g_object[g_objpos++]=0x34040000; // ori a0,zero,0
31+ call_lib_code(LIB_FLOAT | OP_SUB);
32+ } else {
33+ // Main routine of getting float value here
34+ if (b1=='+') g_srcpos++; // Ignore unary '+' operator
35+ next_position();
36+ b1=g_source[g_srcpos];
37+ b2=g_source[g_srcpos+1];
38+ b3=g_source[g_srcpos+2];
39+ if ('0'<=b1 && b1<='9') {
40+ f=strtof((const char*)&g_source[g_srcpos],&err);
41+ if (&g_source[g_srcpos]==err) return ERR_SYNTAX;
42+ g_srcpos=err-g_source;
43+ i=((int*)(&f))[0];
44+ if (i&0xFFFF0000) {
45+ // 32 bit
46+ check_obj_space(2);
47+ g_object[g_objpos++]=0x3C020000|((i>>16)&0x0000FFFF); // lui v0,xxxx
48+ g_object[g_objpos++]=0x34420000|(i&0x0000FFFF); // ori v0,v0,xxxx
49+ } else {
50+ // 16 bit
51+ check_obj_space(1);
52+ g_object[g_objpos++]=0x34020000|(i&0x0000FFFF); // ori v0,zero,xxxx
53+ }
54+ } else {
55+ i=get_var_number();
56+ if (i<0) {
57+ // Must be a function.
58+ return float_function();
59+ }
60+ if (g_source[g_srcpos]!='#') return ERR_SYNTAX;
61+ g_srcpos++;
62+ if (g_source[g_srcpos]=='(') {
63+ // Dimension
64+ g_srcpos++;
65+ return get_dim_value(i);
66+ }
67+ // Simple value
68+ check_obj_space(1);
69+ g_object[g_objpos++]=0x8FC20000|(i*4); // lw v0,xx(s8)
70+ }
71+ }
72+ // No error
73+ return 0;
74+}
75+
76+char* get_float_sub(int pr){
77+ char* err;
78+ enum operator op;
79+ char b1,b2,b3;
80+ int prevpos;
81+ // Get a value in $v0.
82+ err=get_simple_float();
83+ if (err) return err;
84+ while(1){
85+ // Get the operator in op. If not valid operator, simply return without error.
86+ prevpos=g_srcpos;
87+ err=get_floatOperator();
88+ if (err) return 0;
89+ op=g_last_op;
90+ // Compair current and previous operators.
91+ // If the previous operator has higher priolity, return.
92+ if (pr>=priority(op)) {
93+ g_srcpos=prevpos;
94+ return 0;
95+ }
96+ // Store $v0 in stack
97+ g_sdepth+=4;
98+ if (g_maxsdepth<g_sdepth) g_maxsdepth=g_sdepth;
99+ check_obj_space(1);
100+ g_object[g_objpos++]=0xAFA20000|g_sdepth; // sw v0,xx(sp)
101+ // Get next value.
102+ err=get_float_sub(priority(op));
103+ if (err) return err;
104+ // Get value from stack to $a0.
105+ check_obj_space(1);
106+ g_object[g_objpos++]=0x8FA40000|g_sdepth; // lw a0,xx(sp)
107+ g_sdepth-=4;
108+ // Calculation. Result will be in $v0.
109+ err=calculation_float(op);
110+ if (err) return err;
111+ }
112+}
113+
114+char* get_float(){
115+ // Note that this can be called recursively.
116+ // Value may contain function with a parameter of another value.
117+ char* err;
118+ int prevpos;
119+ if (g_sdepth==0) {
120+ // Initialize stack handler
121+ g_maxsdepth=0;
122+ prevpos=g_objpos;
123+ // Stack decrement command will be filled later
124+ check_obj_space(1);
125+ g_objpos++;
126+ }
127+ err=get_float_sub(priority(OP_VOID));
128+ if (err) return err;
129+ if (g_sdepth==0) {
130+ if (g_maxsdepth==0) {
131+ // Stack was not used.
132+ shift_obj(&g_object[prevpos+1],&g_object[prevpos],g_objpos-prevpos-1);
133+ g_objpos--;
134+ } else {
135+ // Stack was used.
136+ check_obj_space(1);
137+ g_object[prevpos]=0x27BD0000 | (0-g_maxsdepth) & 0x0000FFFF; // addiu sp,sp,-xx
138+ g_object[g_objpos++]=0x27BD0000 | g_maxsdepth & 0x0000FFFF; // addiu sp,sp,xx
139+ }
140+ }
141+ g_lastvar=VAR_FLOAT;
142+ return 0;
143+}
\ No newline at end of file
--- mips/trunk/megalopa/string.c (nonexistent)
+++ mips/trunk/megalopa/string.c (revision 268)
@@ -0,0 +1,216 @@
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') {
80+ i=get_var_number();
81+ if (i<0) {
82+ // Function
83+ // String would be pointed by $v0
84+ // Otherwise, it will be assinged in xxx_function() function.
85+ err=str_function();
86+ if (err) return err;
87+ // Temp area would be used when executing.
88+ g_temp_area_used=1;
89+ return 0;
90+ }
91+ if (g_source[g_srcpos]!='$') return ERR_SYNTAX;
92+ g_srcpos++;
93+ // String variable
94+ next_position();
95+ if (g_source[g_srcpos]=='(') {
96+ // A part of string
97+ g_srcpos++;
98+ err=get_value();
99+ if (err) return err;
100+ if (g_source[g_srcpos]==')') {
101+ g_srcpos++;
102+ // Put -1 to $a0
103+ check_obj_space(1);
104+ g_object[g_objpos++]=0x2404FFFF; // addiu a0,zero,-1
105+ } else if (g_source[g_srcpos]==',') {
106+ g_srcpos++;
107+ // Store $v0 in stack
108+ g_sdepth+=4;
109+ if (g_maxsdepth<g_sdepth) g_maxsdepth=g_sdepth;
110+ check_obj_space(1);
111+ g_object[g_objpos++]=0xAFA20000|g_sdepth; // sw v0,xx(sp)
112+ // Get next value
113+ err=get_value();
114+ if (err) return err;
115+ // Copy $v0 to $a0 and get value from stack to $a0.
116+ check_obj_space(2);
117+ g_object[g_objpos++]=0x00402021; // addu a0,v0,zero
118+ g_object[g_objpos++]=0x8FA20000|g_sdepth; // lw v0,xx(sp)
119+ g_sdepth-=4;
120+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
121+ g_srcpos++;
122+ // Temp area will be used when executing.
123+ g_temp_area_used=1;
124+ } else {
125+ return ERR_SYNTAX;
126+ }
127+ // $a1 is var number, $v0 is position, $a0 is length
128+ check_obj_space(1);
129+ g_object[g_objpos++]=0x24050000|(i); // addiu a1,zero,xx
130+ call_lib_code(LIB_MIDSTR);
131+ } else {
132+ // Simple string
133+ check_obj_space(1);
134+ g_object[g_objpos++]=0x8FC20000|(i*4); // lw v0,xx(s8)
135+ // String is pointed by $v0
136+ }
137+ } else {
138+ return ERR_SYNTAX;
139+ }
140+ return 0;
141+}
142+
143+char* get_string_sub(){
144+ char* err;
145+ char b1;
146+ // Obtain initial string
147+ err=simple_string();
148+ if (err) return err;
149+ // Check if connection operator exists
150+ next_position();
151+ b1=g_source[g_srcpos];
152+ if (b1!='+' && b1!='&') return 0; // Exit if connection operator does not exist.
153+ g_srcpos++;
154+ // Connection required.
155+ // Prepare one level of stack for handling
156+ g_sdepth+=4;
157+ if (g_maxsdepth<g_sdepth) g_maxsdepth=g_sdepth;
158+ while(1) {
159+ // Store current pointer in stack
160+ check_obj_space(1);
161+ g_object[g_objpos++]=0xAFA20000|g_sdepth; // sw v0,xx(sp)
162+ // Obtain next string (pointer will be in $v0)
163+ err=simple_string();
164+ if (err) return err;
165+ // Restore previous pointer from stack in $a0 and copy $v0 to $a1
166+ // Call library
167+ check_obj_space(2);
168+ g_object[g_objpos++]=0x8FA40000|g_sdepth; // lw a0,xx(sp)
169+ call_lib_code(LIB_CONNECT_STRING);
170+ // Temp area will be used when executing.
171+ g_temp_area_used=1;
172+ // Check if further connection operator exists
173+ next_position();
174+ b1=g_source[g_srcpos];
175+ if (b1!='+' && b1!='&') break;
176+ g_srcpos++;
177+ }
178+ g_sdepth-=4;
179+ return 0;
180+}
181+
182+char* get_string(){
183+ // This is only the public function.
184+ // Note that this can be called recursively.
185+ // String may contain a function with a parameter of value
186+ // that is a function with a parameter of string.
187+ // Result will be in $v0 as a pointer.
188+ char* err;
189+ char b1;
190+ int i,prevpos;
191+ if (g_sdepth==0) {
192+ // Initialize stack handler
193+ g_maxsdepth=0;
194+ prevpos=g_objpos;
195+ // Stack decrement command will be filled later
196+ check_obj_space(1);
197+ g_objpos++;
198+ }
199+ err=get_string_sub();
200+ if (err) return err;
201+ if (g_sdepth==0) {
202+ if (g_maxsdepth==0) {
203+ // Stack was not used.
204+ shift_obj(&g_object[prevpos+1],&g_object[prevpos],g_objpos-prevpos-1);
205+ g_objpos--;
206+ } else {
207+ // Stack was used.
208+ check_obj_space(1);
209+ g_object[prevpos]=0x27BD0000 | (0-g_maxsdepth) & 0x0000FFFF; // addiu sp,sp,-xx
210+ g_object[g_objpos++]=0x27BD0000 | g_maxsdepth & 0x0000FFFF; // addiu sp,sp,xx
211+ }
212+ }
213+ g_lastvar=VAR_STRING;
214+ return 0;
215+}
216+
--- mips/trunk/megalopa/value.c (nonexistent)
+++ mips/trunk/megalopa/value.c (revision 268)
@@ -0,0 +1,267 @@
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(int i){
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|(i*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+ // Use a stack
30+ g_sdepth+=4;
31+ if (g_maxsdepth<g_sdepth) g_maxsdepth=g_sdepth;
32+ check_obj_space(1);
33+ do {
34+ g_srcpos++;
35+ g_object[g_objpos++]=0xAFA20000|g_sdepth; // sw v0,xx(sp)
36+ err=get_value_sub(priority(OP_VOID));
37+ if (err) return err;
38+ check_obj_space(5);
39+ g_object[g_objpos++]=0x00021080; // sll v0,v0,0x2
40+ g_object[g_objpos++]=0x8FA30000|g_sdepth; // lw v1,xx(sp)
41+ g_object[g_objpos++]=0x00621821; // addu v1,v1,v0
42+ g_object[g_objpos++]=0x8C620000; // lw v0,0(v1)
43+ } while (g_source[g_srcpos]==',');
44+ g_sdepth-=4;
45+ }
46+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
47+ g_srcpos++;
48+ return 0;
49+}
50+
51+char* get_simple_value(void){
52+ int i;
53+ char* err;
54+ char b1,b2;
55+ next_position();
56+ b1=g_source[g_srcpos];
57+ if (b1=='(') {
58+ // (...)
59+ // Parenthesis
60+ g_srcpos++;
61+ next_position();
62+ err=get_value_sub(priority(OP_VOID));
63+ if (err) return err;
64+ next_position();
65+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
66+ g_srcpos++;
67+ } else if (b1=='-') {
68+ // Unary '-' operator
69+ // Note that unary operators ( + and - ) have higher priority than the other operators
70+ g_srcpos++;
71+ err=get_simple_value();
72+ if (err) return err;
73+ check_obj_space(1);
74+ g_object[g_objpos++]=0x00021023; // subu v0,zero,v0
75+ g_intconst=-g_intconst;
76+ } else {
77+ // Main routine of getting value here
78+ if (b1=='+') g_srcpos++; // Ignore unary '+' operator
79+ next_position();
80+ b1=g_source[g_srcpos];
81+ b2=g_source[g_srcpos+1];
82+ if (b1=='0' && b2=='X' || b1=='$') {
83+ // Starts with '0x' or '$'
84+ // Hex number
85+ g_srcpos++;
86+ if (b1=='0') g_srcpos++;
87+ i=0;
88+ while(b1=g_source[g_srcpos]) {
89+ if ('0'<=b1 && b1<='9') {
90+ i*=16;
91+ i+=b1-'0';
92+ } else if ('A'<=b1 && b1<='F') {
93+ i*=16;
94+ i+=b1-'A'+0x0A;
95+ } else {
96+ break;
97+ }
98+ g_srcpos++;
99+ }
100+ g_intconst=i;
101+ if (i&0xFFFF0000) {
102+ // 32 bit
103+ check_obj_space(2);
104+ g_object[g_objpos++]=0x3C020000|((i>>16)&0x0000FFFF); // lui v0,xxxx
105+ g_object[g_objpos++]=0x34420000|(i&0x0000FFFF); // ori v0,v0,xxxx
106+ } else {
107+ // 16 bit
108+ check_obj_space(1);
109+ g_object[g_objpos++]=0x34020000|(i&0x0000FFFF); // ori v0,zero,xxxx
110+ }
111+ } else if ('0'<=b1 && b1<='9') {
112+ // Starts with 0-9
113+ // Decimal number
114+ i=0;
115+ while(b1=g_source[g_srcpos]) {
116+ if ('0'<=b1 && b1<='9') {
117+ i*=10;
118+ i+=b1-'0';
119+ } else {
120+ break;
121+ }
122+ g_srcpos++;
123+ }
124+ // The next character should not be '.' or 'E'.
125+ // Or, it must be recognized as a float value.
126+ if (b1=='.' || b1=='E') return ERR_SYNTAX;
127+ g_intconst=i;
128+ if (i&0xFFFF0000) {
129+ // 32 bit
130+ check_obj_space(2);
131+ g_object[g_objpos++]=0x3C020000|((i>>16)&0x0000FFFF); // lui v0,xxxx
132+ g_object[g_objpos++]=0x34420000|(i&0x0000FFFF); // ori v0,v0,xxxx
133+ } else {
134+ // 16 bit
135+ check_obj_space(1);
136+ g_object[g_objpos++]=0x34020000|(i&0x0000FFFF); // ori v0,zero,xxxx
137+ }
138+ } else {
139+ g_valueisconst=0;
140+ i=get_var_number();
141+ if (i<0) {
142+ // Must be a function.
143+ return function();
144+ }
145+ if (g_source[g_srcpos]=='(') {
146+ // Dimension
147+ g_srcpos++;
148+ return get_dim_value(i);
149+ }
150+ // Simple value
151+ check_obj_space(1);
152+ g_object[g_objpos++]=0x8FC20000|(i*4); // lw v0,xx(s8)
153+ }
154+ }
155+ // No error
156+ return 0;
157+}
158+
159+char* get_value_sub(int pr){
160+ char* err;
161+ enum operator op;
162+ char b1,b2,b3;
163+ int prevpos;
164+ // Get a value in $v0.
165+ err=get_simple_value();
166+ if (err) return err;
167+ while(1){
168+ // Get the operator in op. If not valid operator, simply return without error.
169+ prevpos=g_srcpos;
170+ err=get_operator();
171+ if (err) return 0;
172+ op=g_last_op;
173+ // Compair current and previous operators.
174+ // If the previous operator has higher priolity, return.
175+ if (pr>=priority(op)) {
176+ g_srcpos=prevpos;
177+ return 0;
178+ }
179+ // Store $v0 in stack
180+ g_sdepth+=4;
181+ if (g_maxsdepth<g_sdepth) g_maxsdepth=g_sdepth;
182+ check_obj_space(1);
183+ g_object[g_objpos++]=0xAFA20000|g_sdepth; // sw v0,xx(sp)
184+ // Get next value.
185+ err=get_value_sub(priority(op));
186+ if (err) return err;
187+ // Get value from stack to $v1.
188+ check_obj_space(1);
189+ g_object[g_objpos++]=0x8FA30000|g_sdepth; // lw v1,xx(sp)
190+ g_sdepth-=4;
191+ // Calculation. Result will be in $v0.
192+ err=calculation(op);
193+ if (err) return err;
194+ }
195+}
196+
197+char* get_value(){
198+ // This is only the public function.
199+ // Note that this can be called recursively.
200+ // Value may contain function with a parameter of another value.
201+ char* err;
202+ int prevpos;
203+ if (g_sdepth==0) {
204+ // Initialize stack handler
205+ g_maxsdepth=0;
206+ prevpos=g_objpos;
207+ // Stack decrement command will be filled later
208+ check_obj_space(1);
209+ g_objpos++;
210+ }
211+ err=get_value_sub(priority(OP_VOID));
212+ if (err) return err;
213+ if (g_sdepth==0) {
214+ if (g_maxsdepth==0) {
215+ // Stack was not used.
216+ shift_obj(&g_object[prevpos+1],&g_object[prevpos],g_objpos-prevpos-1);
217+ g_objpos--;
218+ } else {
219+ // Stack was used.
220+ check_obj_space(1);
221+ g_object[prevpos]=0x27BD0000 | (0-g_maxsdepth) & 0x0000FFFF; // addiu sp,sp,-xx
222+ g_object[g_objpos++]=0x27BD0000 | g_maxsdepth & 0x0000FFFF; // addiu sp,sp,xx
223+ }
224+ }
225+ g_lastvar=VAR_INTEGER;
226+ return 0;
227+}
228+
229+char* get_floatOrValue(){
230+ char* err;
231+ char b;
232+ int opos,spos,sdpt;
233+ sdpt=g_sdepth;
234+ opos=g_objpos;
235+ spos=g_srcpos;
236+ // First try integer.
237+ // Integer value has the higher priolity than float value.
238+ err=get_value();
239+ b=g_source[g_srcpos];
240+ if (err || b=='#') {
241+ // Value is not integer. Let's try float.
242+ g_sdepth=sdpt;
243+ g_objpos=opos;
244+ g_srcpos=spos;
245+ return get_float();
246+ } else {
247+ // Value was recognized as an integer.
248+ return 0;
249+ }
250+}
251+
252+char* get_stringFloatOrValue(){
253+ char* err;
254+ int opos,spos;
255+ opos=g_objpos;
256+ spos=g_srcpos;
257+ // First try string, float, then integer.
258+ err=get_string();
259+ if (err) {
260+ g_objpos=opos;
261+ g_srcpos=spos;
262+ return get_floatOrValue();
263+ } else {
264+ return 0;
265+ }
266+}
267+
--- mips/trunk/megalopa/compiler.c (nonexistent)
+++ mips/trunk/megalopa/compiler.c (revision 268)
@@ -0,0 +1,151 @@
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+ next_position();
82+ for(len=0;str[len];len++);
83+ if (!strncmp(g_source+g_srcpos,str,len)) {
84+ if ('A'<=str[len-1] && str[len-1]<='Z') {
85+ // When the last character of str is alphabet,
86+ // the next character in source must be space, enter, or ':'.
87+ if (0x20<g_source[g_srcpos+len] && g_source[g_srcpos+len]!=':') return 0;
88+ }
89+ // String matches in the current position in source.
90+ g_srcpos+=len;
91+ return len;
92+ } else {
93+ // String didn't match.
94+ return 0;
95+ }
96+}
97+
98+int endOfStatement(){
99+ unsigned char b;
100+ next_position();
101+ b=g_source[g_srcpos];
102+ return (b<0x20 || b==':') ? 1:0;
103+}
104+
105+char* compile_line(void){
106+ char b1;
107+ char* err;
108+ g_line++;
109+ g_fileline++;
110+ // Check if line number exists
111+ next_position();
112+ b1=g_source[g_srcpos];
113+ if (b1<0x20) {
114+ // The end of line.
115+ // Don't add $s6-setting command.
116+ if (g_source[g_srcpos]==0x0D && g_source[g_srcpos+1]==0x0A) g_srcpos++;
117+ g_srcpos++;
118+ return 0;
119+ } else if ('0'<=b1 && b1<='9') {
120+ // Line number exists
121+ err=get_label();
122+ if (err) return err;
123+ g_line=g_label;
124+ }
125+ // Store line number in $s6
126+ if (!(g_line&0xFFFF0000)) {
127+ // Line number must be less than 65536.
128+ // If not, it is invalid number.
129+ // Check existing line with the same number here.
130+ if (search_label(g_line)) {
131+ // Error: duplicate lines
132+ printstr("Line ");
133+ printstr(resolve_label(g_line));
134+ return ERR_MULTIPLE_LABEL;
135+ }
136+ check_obj_space(1);
137+ g_object[g_objpos++]=0x34160000|g_line; //ori s6,zero,xxxx;
138+ }
139+ while(g_source[g_srcpos]!=0x0D && g_source[g_srcpos]!=0x0A){
140+ err=statement();
141+ if (err) return err;
142+ next_position();
143+ if (g_source[g_srcpos]==':') {
144+ g_srcpos++;
145+ next_position();
146+ }
147+ }
148+ if (g_source[g_srcpos]==0x0D && g_source[g_srcpos+1]==0x0A) g_srcpos++;
149+ g_srcpos++;
150+ return 0;
151+}
\ No newline at end of file
--- mips/trunk/megalopa/file.c (nonexistent)
+++ mips/trunk/megalopa/file.c (revision 268)
@@ -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/trunk/megalopa/keyinput.h (nonexistent)
+++ mips/trunk/megalopa/keyinput.h (revision 268)
@@ -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/trunk/megalopa/linker.c (nonexistent)
+++ mips/trunk/megalopa/linker.c (revision 268)
@@ -0,0 +1,390 @@
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+ }
101+ }
102+ // Line number not found.
103+ return 0;
104+ } else {
105+ // Line number
106+ search1=0x34160000|label; //ori s6,zero,xxxx;
107+ for(i=0;i<g_objpos;i++){
108+ code=g_object[i];
109+ if (code==search1) {
110+ // Line number found
111+ return &(g_object[i]);
112+ }
113+ if (code&0xFFFF0000==0x04110000) {
114+ // "bgezal zero," assembly found. Skip following block (strig).
115+ i+=code&0x0000FFFF;
116+ }
117+ }
118+ // Line number not found.
119+ return 0;
120+ }
121+}
122+
123+void* search_breakout(unsigned int start, int* prevcode){
124+ unsigned int pos,code1,depth;
125+ // Start search from start point where BREAK statement is used.
126+ depth=0;
127+ for(pos=start;pos<g_objpos;pos++){
128+ code1=g_object[pos];
129+ switch(code1>>16){
130+ case 0x0411:
131+ // "bgezal zero," assembly found. Skip following block (strig).
132+ pos+=code1&0x0000FFFF;
133+ break;
134+ case 0x0820: // FOR
135+ case 0x0821: // WHILE
136+ case 0x0822: // DO
137+ depth++;
138+ break;
139+ case 0x0830: // NEXT
140+ case 0x0831: // WEND
141+ case 0x0832: // LOOP
142+ if (0<depth) {
143+ depth--;
144+ break;
145+ }
146+ // Destination found.
147+ // Previous code will be also set if required for CONTINUE statement.
148+ if (prevcode) prevcode[0]=g_object[pos-1];
149+ return (void*)&g_object[pos];
150+ default:
151+ break;
152+ }
153+ }
154+ return 0;
155+}
156+
157+void* search_ifout(unsigned int start){
158+ unsigned int pos,code1,depth;
159+ // Start search from start point where BREAK statement is used.
160+ depth=0;
161+ for(pos=start;pos<g_objpos;pos++){
162+ code1=g_object[pos];
163+ switch(code1>>16){
164+ case 0x0411:
165+ // "bgezal zero," assembly found. Skip following block (strig).
166+ pos+=code1&0x0000FFFF;
167+ break;
168+ case 0x3000: // Block marker
169+ if (code1==0x30008000) {
170+ // end block
171+ if (0<depth) {
172+ depth--;
173+ break;
174+ }
175+ // Destination found.
176+ return (void*)&g_object[pos];
177+ } else if (code1==0x30000000) {
178+ // begin block
179+ depth++;
180+ break;
181+ } else {
182+ break;
183+ }
184+ default:
185+ break;
186+ }
187+ }
188+ return 0;
189+}
190+
191+/*
192+ Following codes are dedicated to specific use:
193+ 0x0411xxxx: String/data block
194+ Use 0x0413xxxx (bzegall zero,xxxx) for other cases to get PC to $ra
195+ 0x0810xxxx, 0x0811xxxx: GOTO statement
196+ 0x0812xxxx, 0x0813xxxx: GOSUB statement
197+ 0x0814xxxx, 0x0815xxxx: SOUND etc, for setting v0 as pointer to DATA array.
198+ 0x0816xxxx: BREAK statemant and relatives
199+ 0x08160000: BREAK
200+ 0x08160008: CONTINUE
201+ 0x08160100: Jump to next ELSE, ELSEIF or ENDIF
202+ 0x082xyyyy: Begin block (FOR/DO/WHILE)
203+ 0x083xyyyy: End block (NEXT/LOOP/WEND)
204+ 0x00000020, 0x00000021,
205+ 0x00000022, 0x00000023: Marker for begining the DATA region.
206+ MLB 2 bits show skip byte length in DATA.
207+ 0x30000000: Begin block (IF-THEN-ELSEIF-ELSE-ENDIF)
208+ 0x30008000: End block (IF-THEN-ELSEIF-ELSE-ENDIF)
209+ 0x3000Fxxx: General purpose NOP with value 0x0000-0x0FFF.
210+
211+ IF-THEN-ELSEIF-ELSE-ENDIF is written as follows:
212+ IF-THEN: 0x30000000 0x10400000 0x30000000
213+ ELSEIF-THEN: 0x08160100 0x30008000 (conditional expression) 0x10400000 0x30000000
214+ ELSE: 0x08160100 0x30008000 0x30000000
215+ ENDIF: 0x30008000 0x30008000
216+ , where "0x10400000 0x30000000" and "0x08160100 0x30008000" will be replaced by
217+ codes jumping to next 0x30008000. The 0x30000000 - 0x30008000 blocks will be skipped.
218+*/
219+
220+char* link(void){
221+ int pos;
222+ unsigned int code1,code2,label;
223+ g_fileline=0;
224+ for(pos=0;pos<g_objpos;pos++){
225+ code1=g_object[pos];
226+ switch(code1>>16){
227+ case 0x0411:
228+ // "bgezal zero," assembly found. Skip following block (strig).
229+ pos+=code1&0x0000FFFF;
230+ break;
231+ case 0x3416:
232+ // "ori s6,zero,xxxx" found this is the first word in a line.
233+ g_fileline++;
234+ g_line=code1&0x0000FFFF;
235+ break;
236+ case 0x0810:
237+ // GOTO
238+ code2=g_object[pos+1];
239+ if ((code2&0xFFFF0000)!=0x08110000) continue;
240+ code1&=0x0000FFFF;
241+ code2&=0x0000FFFF;
242+ label=(code1<<16)|code2;
243+ code1=(int)search_label(label);
244+ g_label=label;
245+ if (!code1) return ERR_LABEL_NF;
246+ code1&=0x0FFFFFFF;
247+ code1>>=2;
248+ code1|=0x08000000; // j xxxx
249+ g_object[pos++]=code1;
250+ g_object[pos]=0x00000000; // nop
251+ break;
252+ case 0x0812:
253+ // GOSUB
254+ code2=g_object[pos+1];
255+ if ((code2&0xFFFF0000)!=0x08130000) continue;
256+ code1&=0x0000FFFF;
257+ code2&=0x0000FFFF;
258+ label=(code1<<16)|code2;
259+ code2=(int)search_label(label);
260+ g_label=label;
261+ if (!code2) return ERR_LABEL_NF;
262+ code2&=0x0FFFFFFF;
263+ code2>>=2;
264+ code2|=0x08000000; // j xxxx
265+ g_object[pos++]=0x00000000; // nop
266+ g_object[pos]=code2;
267+ break;
268+ case 0x0814:
269+ // SOUND etc, for setting v0 as pointer to label/line
270+ code2=g_object[pos+1];
271+ if ((code2&0xFFFF0000)!=0x08150000) continue;
272+ code1&=0x0000FFFF;
273+ code2&=0x0000FFFF;
274+ label=(code1<<16)|code2;
275+ code1=(int)search_label(label);
276+ g_label=label;
277+ if (!code1) return ERR_LABEL_NF;
278+ g_object[pos++]=0x3C020000|((code1>>16)&0x0000FFFF); // lui v0,xxxx
279+ g_object[pos] =0x34420000|(code1&0x0000FFFF); // ori v0,v0,xxxx
280+ break;
281+ case 0x0816:
282+ switch(code1&0xFFFF) {
283+ case 0x0000:
284+ // BREAK statement
285+ // Find next the NEXT or WHILE statement and insert jump code after this.
286+ g_label=g_line;
287+ code1=(int)search_breakout(pos,0);
288+ if (!code1) return ERR_INVALID_BREAK;
289+ code1&=0x0FFFFFFF;
290+ code1>>=2;
291+ code1|=0x08000000; // j xxxx
292+ g_object[pos]=code1;
293+ break;
294+ case 0x0008:
295+ // CONTINUE statement
296+ // Find next the NEXT or WHILE statement and insert jump code after this.
297+ g_label=g_line;
298+ code1=(int)search_breakout(pos,&g_temp);
299+ if (!code1) return ERR_INVALID_BREAK;
300+ if (0x3000F000 == (g_temp&0xFFFFF000)) {
301+ // WEND or LOOP statement found
302+ code1-=(g_temp&0x0FFF)<<2;
303+ } else {
304+ // NEXT statement found
305+ code1-=3<<2;
306+ }
307+ code1&=0x0FFFFFFF;
308+ code1>>=2;
309+ code1|=0x08000000; // j xxxx
310+ g_object[pos]=code1;
311+ break;
312+ case 0x0100:
313+ // Jump to next ENDIF
314+ g_label=g_line;
315+ // "pos+2" is for skipping next code (must be 0x30008000)
316+ code1=(int)search_ifout(pos+2);
317+ if (!code1) return ERR_INVALID_ELSEIF;
318+ code1&=0x0FFFFFFF;
319+ code1>>=2;
320+ code1|=0x08000000; // j xxxx
321+ g_object[pos]=code1;
322+ break;
323+ default:
324+ break;
325+ }
326+ break;
327+ case 0x3000:
328+ // Block marker
329+ switch(code1&0xFFFF) {
330+ case 0x0000:
331+ // Begin if block
332+ if (g_object[pos-1]==0x10400000) { // beq v0,zero,xxxx
333+ // IF-THEN or ELSEIF-THEN
334+ // Jump to next ELSE, ELSEIF or ENDIF
335+ g_label=g_line;
336+ // "pos+1" is for skipping current code (0x30000000)
337+ code1=(int)search_ifout(pos+1);
338+ if (!code1) return ERR_INVALID_ELSEIF;
339+ code1-=(int)(&g_object[pos]);
340+ code1>>=2;
341+ code1&=0x0000FFFF;
342+ code1|=0x10400000; // beq v0,zero,xxxx
343+ g_object[pos-1]=code1;
344+ break;
345+ }
346+ break;
347+ default:
348+ break;
349+ }
350+ break;
351+ case 0x0820: // FOR
352+ case 0x0830: // NEXT
353+ case 0x0821: // WHILE
354+ case 0x0831: // WEND
355+ case 0x0822: // DO
356+ case 0x0832: // WHILE
357+ // These are used for detecing the depth of structures.
358+ // Change them to stack increase/decrease commands.
359+ g_object[pos]=0x27BD0000|(code1&0x0000FFFF); //// addiu sp,sp,xx
360+ break;
361+ case 0x2407: // addiu a3,zero,xxxx
362+ if (g_object[pos-1]!=0x02E0F809) break; // jalr ra,s7
363+ // call_lib_code(x)
364+ switch(code1&0x0000FFFF){
365+ case LIB_RESTORE:
366+ // Convert label data to pointer if not dynamic
367+ code1=g_object[pos-3];
368+ code2=g_object[pos-2];
369+ if ((code1>>16)!=0x3C02) break; // lui v0,xxxx
370+ if ((code2>>16)!=0x3442) break; // ori v0,v0,xxxx
371+ label=(code1<<16)|(code2&0x0000FFFF);
372+ code1=(int)search_label(label);
373+ g_label=label;
374+ if (!code1) return ERR_LABEL_NF;
375+ code2=code1&0x0000FFFF;
376+ code1=code1>>16;
377+ g_object[pos-3]=0x3C020000|code1; // lui v0,xxxx
378+ g_object[pos-2]=0x34420000|code2; // ori v0,v0,xxxx
379+ g_object[pos]=0x24070000|LIB_RESTORE2; // addiu a3,zero,xxxx
380+ break;
381+ default:
382+ break;
383+ }
384+ break;
385+ default:
386+ break;
387+ }
388+ }
389+ return 0;
390+}
\ No newline at end of file
--- mips/trunk/megalopa/operator.c (nonexistent)
+++ mips/trunk/megalopa/operator.c (revision 268)
@@ -0,0 +1,273 @@
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+ // All the calculations will be done in library code, lib_float function (see below).
217+ call_lib_code(LIB_FLOAT | op);
218+ return 0;
219+}
220+
221+int lib_float(int ia0,int iv0, enum operator a1){
222+ // This function was called from _call_library().
223+ // Variable types must be all int.
224+ // Casting cannot be used.
225+ // Instead, by using pointer, put as int value, get as float value,
226+ // calculate, put as float value, then get as int value for returning.
227+ volatile float a0,v0;
228+ ((int*)(&a0))[0]=ia0;
229+ ((int*)(&v0))[0]=iv0;
230+ switch(a1){
231+ case OP_EQ:
232+ v0= a0==v0?1:0;
233+ break;
234+ case OP_NEQ:
235+ v0= a0!=v0?1:0;
236+ break;
237+ case OP_LT:
238+ v0= a0<v0?1:0;
239+ break;
240+ case OP_LTE:
241+ v0= a0<=v0?1:0;
242+ break;
243+ case OP_MT:
244+ v0= a0>v0?1:0;
245+ break;
246+ case OP_MTE:
247+ v0= a0>=v0?1:0;
248+ break;
249+ case OP_ADD:
250+ v0= a0+v0;
251+ break;
252+ case OP_SUB:
253+ v0= a0-v0;
254+ break;
255+ case OP_MUL:
256+ v0= a0*v0;
257+ break;
258+ case OP_DIV:
259+ if (v0==0) err_div_zero();
260+ v0= a0/v0;
261+ break;
262+ case OP_OR:
263+ v0= a0||v0?1:0;
264+ break;
265+ case OP_AND:
266+ v0= a0&&v0?1:0;
267+ break;
268+ default:
269+ err_unknown();
270+ return 0;
271+ }
272+ return ((int*)(&v0))[0];
273+};
\ No newline at end of file
--- mips/trunk/megalopa/sdfsio370f.h (nonexistent)
+++ mips/trunk/megalopa/sdfsio370f.h (revision 268)
@@ -0,0 +1,2357 @@
1+// sdfsio370f.h
2+// PIC32MX370F512HでSPI2接続されたSDカードにアクセスする
3+// sdfsio370fLib.aを利用するためのヘッダーファイル
4+// FSIO.h,FSconfig.h,FSDefs.hから抜粋 by K.Tanaka
5+//
6+// サポート
7+// FAT32,書き込み,ファイルサーチ,Dir
8+// 未サポート
9+// LongFileName,FSfprintf,format,FSGetDiskProperties
10+// 同時オープン数 3
11+
12+/******************************************************************************
13+ *
14+ * Microchip Memory Disk Drive File System
15+ *
16+ ******************************************************************************
17+ * FileName: FSIO.h
18+ * Dependencies: GenericTypeDefs.h
19+ * FSconfig.h
20+ * FSDefs.h
21+ * stddef.h
22+ * Processor: PIC18/PIC24/dsPIC30/dsPIC33/PIC32
23+ * Compiler: C18/C30/C32
24+ * Company: Microchip Technology, Inc.
25+ * Version: 1.3.0
26+ *
27+ * Software License Agreement
28+ *
29+ * The software supplied herewith by Microchip Technology Incorporated
30+ * (the 鼎ompany・ for its PICmicroョ Microcontroller is intended and
31+ * supplied to you, the Company痴 customer, for use solely and
32+ * exclusively on Microchip PICmicro Microcontroller products. The
33+ * software is owned by the Company and/or its supplier, and is
34+ * protected under applicable copyright laws. All rights are reserved.
35+ * Any use in violation of the foregoing restrictions may subject the
36+ * user to criminal sanctions under applicable laws, as well as to
37+ * civil liability for the breach of the terms and conditions of this
38+ * license.
39+ *
40+ * THIS SOFTWARE IS PROVIDED IN AN 鄭S IS・CONDITION. NO WARRANTIES,
41+ * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
42+ * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
43+ * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
44+ * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
45+ * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
46+ *
47+*****************************************************************************/
48+
49+#ifndef FS_DOT_H
50+#define FS_DOT_H
51+
52+#define MDD_MediaInitialize MDD_SDSPI_MediaInitialize
53+#define MDD_MediaDetect MDD_SDSPI_MediaDetect
54+#define MDD_SectorRead MDD_SDSPI_SectorRead
55+#define MDD_SectorWrite MDD_SDSPI_SectorWrite
56+#define MDD_InitIO MDD_SDSPI_InitIO
57+#define MDD_ShutdownMedia MDD_SDSPI_ShutdownMedia
58+#define MDD_WriteProtectState MDD_SDSPI_WriteProtectState
59+
60+#define ALLOW_FILESEARCH
61+#define ALLOW_WRITES
62+#define ALLOW_DIRS
63+#define SUPPORT_FAT32
64+
65+// Summary: An enumeration used for various error codes.
66+// Description: The CETYPE enumeration is used to indicate different error conditions during device operation.
67+typedef enum _CETYPE
68+{
69+ CE_GOOD = 0, // No error
70+ CE_ERASE_FAIL, // An erase failed
71+ CE_NOT_PRESENT, // No device was present
72+ CE_NOT_FORMATTED, // The disk is of an unsupported format
73+ CE_BAD_PARTITION, // The boot record is bad
74+ CE_UNSUPPORTED_FS, // The file system type is unsupported
75+ CE_INIT_ERROR, // An initialization error has occured
76+ CE_NOT_INIT, // An operation was performed on an uninitialized device
77+ CE_BAD_SECTOR_READ, // A bad read of a sector occured
78+ CE_WRITE_ERROR, // Could not write to a sector
79+ CE_INVALID_CLUSTER, // Invalid cluster value > maxcls
80+ CE_FILE_NOT_FOUND, // Could not find the file on the device
81+ CE_DIR_NOT_FOUND, // Could not find the directory
82+ CE_BAD_FILE, // File is corrupted
83+ CE_DONE, // No more files in this directory
84+ CE_COULD_NOT_GET_CLUSTER, // Could not load/allocate next cluster in file
85+ CE_FILENAME_2_LONG, // A specified file name is too long to use
86+ CE_FILENAME_EXISTS, // A specified filename already exists on the device
87+ CE_INVALID_FILENAME, // Invalid file name
88+ CE_DELETE_DIR, // The user tried to delete a directory with FSremove
89+ CE_DIR_FULL, // All root dir entry are taken
90+ CE_DISK_FULL, // All clusters in partition are taken
91+ CE_DIR_NOT_EMPTY, // This directory is not empty yet, remove files before deleting
92+ CE_NONSUPPORTED_SIZE, // The disk is too big to format as FAT16
93+ CE_WRITE_PROTECTED, // Card is write protected
94+ CE_FILENOTOPENED, // File not opened for the write
95+ CE_SEEK_ERROR, // File location could not be changed successfully
96+ CE_BADCACHEREAD, // Bad cache read
97+ CE_CARDFAT32, // FAT 32 - card not supported
98+ CE_READONLY, // The file is read-only
99+ CE_WRITEONLY, // The file is write-only
100+ CE_INVALID_ARGUMENT, // Invalid argument
101+ CE_TOO_MANY_FILES_OPEN, // Too many files are already open
102+ CE_UNSUPPORTED_SECTOR_SIZE // Unsupported sector size
103+} CETYPE;
104+
105+
106+// Summary: A macro indicating a dir entry was found
107+// Description: The FOUND macro indicates that a directory entry was found in the specified position
108+#define FOUND 0
109+
110+// Summary: A macro indicating no dir entry was found
111+// Description: The NOT_FOUND macro indicates that the specified directory entry to load was deleted
112+#define NOT_FOUND 1
113+
114+// Summary: A macro indicating that no more files were found
115+// Description: The NO_MORE macro indicates that there are no more directory entries to search for
116+#define NO_MORE 2
117+
118+
119+
120+// Summary: A macro indicating the device is formatted with FAT12
121+// Description: The FAT12 macro is used to indicate that the file system on the device being accessed is a FAT12 file system.
122+#define FAT12 1
123+
124+// Summary: A macro indicating the device is formatted with FAT16
125+// Description: The FAT16 macro is used to indicate that the file system on the device being accessed is a FAT16 file system.
126+#define FAT16 2
127+
128+// Summary: A macro indicating the device is formatted with FAT32
129+// Description: The FAT32 macro is used to indicate that the file system on the device being accessed is a FAT32 file system.
130+#define FAT32 3
131+
132+
133+
134+// Summary: A read-only attribute macro
135+// Description: A macro for the read-only attribute. A file with this attribute should not be written to. Note that this
136+// attribute will not actually prevent a write to the file; that functionality is operating-system dependant. The
137+// user should take care not to write to a read-only file.
138+#define ATTR_READ_ONLY 0x01
139+
140+// Summary: A hidden attribute macro
141+// Description: A macro for the hidden attribute. A file with this attribute may be hidden from the user, depending on the
142+// implementation of the operating system.
143+#define ATTR_HIDDEN 0x02
144+
145+// Summary: A system attribute macro
146+// Description: A macro for the system attribute. A file with this attribute is used by the operating system, and should not be
147+// modified. Note that this attribute will not actually prevent a write to the file.
148+#define ATTR_SYSTEM 0x04
149+
150+// Summary: A volume attribute macro
151+// Description: A macro for the volume attribute. If the first directory entry in the root directory has the volume attribute set,
152+// the device will use the name in that directory entry as the volume name.
153+#define ATTR_VOLUME 0x08
154+
155+// Summary: A macro for the attributes for a long-file name entry
156+// Description: A macro for the long-name attributes. If a directory entry is used in a long-file name implementation, it will have
157+// all four lower bits set. This indicates that any software that does not support long file names should ignore that
158+// entry.
159+#define ATTR_LONG_NAME 0x0f
160+
161+// Summary: A directory attribute macro
162+// Description: A macro for the directory attribute. If a directory entry has this attribute set, the file it points to is a directory-
163+// type file, and will contain directory entries that point to additional directories or files.
164+#define ATTR_DIRECTORY 0x10
165+
166+// Summary: An archive attribute macro
167+// Description: A macro for the archive attribute. This attribute will indicate to some archiving programs that the file with this
168+// attribute needs to be backed up. Most operating systems create files with the archive attribute set.
169+#define ATTR_ARCHIVE 0x20
170+
171+// Summary: A macro for all attributes
172+// Description: A macro for all attributes. The search functions in this library require an argument that determines which attributes
173+// 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
174+// of its attributes.
175+#define ATTR_MASK 0x3f
176+
177+
178+
179+// Summary: A macro to indicate an empty FAT entry
180+// Description: The CLUSTER_EMPTY value is used to indicate that a FAT entry and it's corresponding cluster are available.
181+#define CLUSTER_EMPTY 0x0000
182+
183+// Summary: A macro to indicate the last cluster value for FAT12
184+// Description: The LAST_CLUSTER_FAT12 macro is used when reading the FAT to indicate that the next FAT12 entry for a file contains
185+// the end-of-file value.
186+#define LAST_CLUSTER_FAT12 0xff8
187+
188+// Summary: A macro to indicate the last cluster value for FAT16
189+// Description: The LAST_CLUSTER_FAT16 macro is used when reading the FAT to indicate that the next FAT16 entry for a file contains
190+// the end-of-file value.
191+#define LAST_CLUSTER_FAT16 0xfff8
192+
193+// Summary: A macro to indicate the last allocatable cluster for FAT12
194+// Description: The END_CLUSTER_FAT12 value is used as a comparison in FAT12 to determine that the firmware has reached the end of
195+// the range of allowed allocatable clusters.
196+#define END_CLUSTER_FAT12 0xFF7
197+
198+// Summary: A macro to indicate the last allocatable cluster for FAT16
199+// Description: The END_CLUSTER_FAT16 value is used as a comparison in FAT16 to determine that the firmware has reached the end of
200+// the range of allowed allocatable clusters.
201+#define END_CLUSTER_FAT16 0xFFF7
202+
203+// Summary: A macro to indicate the failure of the ReadFAT function
204+// Description: The CLUSTER_FAIL_FAT16 macro is used by the ReadFAT function to indicate that an error occured reading a FAT12 or FAT16
205+// file allocation table. Note that since '0xFFF8' is used for the last cluster return value in the FAT16 implementation
206+// the end-of-file value '0xFFFF' can be used to indicate an error condition.
207+#define CLUSTER_FAIL_FAT16 0xFFFF
208+
209+
210+
211+#ifdef SUPPORT_FAT32
212+ // Summary: A macro to indicate the last cluster value for FAT32
213+ // Description: The LAST_CLUSTER_FAT32 macro is used when reading the FAT to indicate that the next FAT32 entry for a file contains
214+ // the end-of-file value.
215+ #define LAST_CLUSTER_FAT32 0x0FFFFFF8
216+
217+ // Summary: A macro to indicate the last allocatable cluster for FAT32
218+ // Description: The END_CLUSTER_FAT32 value is used as a comparison in FAT32 to determine that the firmware has reached the end of
219+ // the range of allowed allocatable clusters.
220+ #define END_CLUSTER_FAT32 0x0FFFFFF7
221+
222+ // Summary: A macro to indicate the failure of the ReadFAT function
223+ // Description: The CLUSTER_FAIL_FAT32 macro is used by the ReadFAT function to indicate that an error occured reading a FAT32
224+ // file allocation able.
225+ #define CLUSTER_FAIL_FAT32 0x0FFFFFFF
226+
227+#endif
228+
229+// Summary: A macro indicating the number of bytes in a directory entry.
230+// Description: The NUMBER_OF_BYTES_IN_DIR_ENTRY macro represents the number of bytes in one directory entry. It is used to calculate
231+// the number of sectors in the root directory based on information in the boot sector.
232+#define NUMBER_OF_BYTES_IN_DIR_ENTRY 32
233+
234+
235+
236+// Summary: A macro for a deleted dir entry marker.
237+// Description: The DIR_DEL macro is used to mark a directory entry as deleted. When a file is deleted, this value will replace the
238+// first character in the file name, and will indicate that the file the entry points to was deleted.
239+#define DIR_DEL 0xE5
240+
241+// Summary: A macro for the last dir entry marker.
242+// 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
243+// deleted entries start with the DIR_DEL character, a 0 will mark the end of the in-use or previously used group of
244+// entries in a directory
245+#define DIR_EMPTY 0
246+
247+
248+
249+// Summary: A macro used to indicate the length of an 8.3 file name
250+// Description: The DIR_NAMESIZE macro is used when validing the name portion of 8.3 filenames
251+#define DIR_NAMESIZE 8
252+
253+// Summary: A macro used to indicate the length of an 8.3 file extension
254+// Description: The DIR_EXTENSION macro is used when validating the extension portion of 8.3 filenames
255+#define DIR_EXTENSION 3
256+
257+// Summary: A macro used to indicate the length of an 8.3 file name and extension
258+// Description: The DIR_NAMECOMP macro is used when validating 8.3 filenames
259+#define DIR_NAMECOMP (DIR_NAMESIZE+DIR_EXTENSION)
260+
261+
262+
263+// Summary: A macro to write a byte to RAM
264+// Description: The RAMwrite macro is used to write a byte of data to a RAM array
265+#define RAMwrite( a, f, d) *(a+f) = d
266+
267+// Summary: A macro to read a byte from RAM
268+// Description: The RAMread macro is used to read a byte of data from a RAM array
269+#define RAMread( a, f) *(a+f)
270+
271+// Summary: A macro to read a 16-bit word from RAM
272+// Description: The RAMreadW macro is used to read two bytes of data from a RAM array
273+#define RAMreadW( a, f) *(WORD *)(a+f)
274+
275+// Summary: A macro to read a 32-bit word from RAM
276+// Description: The RAMreadD macro is used to read four bytes of data from a RAM array
277+#define RAMreadD( a, f) *(DWORD *)(a+f)
278+
279+
280+
281+#ifndef EOF
282+ // Summary: Indicates error conditions or end-of-file conditions
283+ // Description: The EOF macro is used to indicate error conditions in some function calls. It is also used to indicate
284+ // that the end-of-file has been reached.
285+ #define EOF ((int)-1)
286+#endif
287+
288+
289+
290+// Summary: A structure containing information about the device.
291+// Description: The DISK structure contains information about the device being accessed.
292+typedef struct
293+{
294+ BYTE * buffer; // Address of the global data buffer used to read and write file information
295+ DWORD firsts; // Logical block address of the first sector of the FAT partition on the device
296+ DWORD fat; // Logical block address of the FAT
297+ DWORD root; // Logical block address of the root directory
298+ DWORD data; // Logical block address of the data section of the device.
299+ WORD maxroot; // The maximum number of entries in the root directory.
300+ DWORD maxcls; // The maximum number of clusters in the partition.
301+ DWORD sectorSize; // The size of a sector in bytes
302+ DWORD fatsize; // The number of sectors in the FAT
303+ BYTE fatcopy; // The number of copies of the FAT in the partition
304+ BYTE SecPerClus; // The number of sectors per cluster in the data region
305+ BYTE type; // The file system type of the partition (FAT12, FAT16 or FAT32)
306+ BYTE mount; // Device mount flag (TRUE if disk was mounted successfully, FALSE otherwise)
307+#if defined __PIC32MX__ || defined __C30__
308+} __attribute__ ((packed)) DISK;
309+#else
310+} DISK;
311+#endif
312+
313+
314+#ifdef __18CXX
315+ // Summary: A 24-bit data type
316+ // Description: The SWORD macro is used to defined a 24-bit data type. For 16+ bit architectures, this must be represented as
317+ // an array of three bytes.
318+ typedef unsigned short long SWORD;
319+#else
320+ // Summary: A 24-bit data type
321+ // Description: The SWORD macro is used to defined a 24-bit data type. For 16+ bit architectures, this must be represented as
322+ // an array of three bytes.
323+ typedef struct
324+ {
325+ unsigned char array[3];
326+#if defined __PIC32MX__ || defined __C30__
327+ } __attribute__ ((packed)) SWORD;
328+#else
329+ } SWORD;
330+#endif
331+#endif
332+
333+
334+
335+// Summary: A structure containing the bios parameter block for a FAT12 file system (in the boot sector)
336+// Description: The _BPB_FAT12 structure provides a layout of the "bios parameter block" in the boot sector of a FAT12 partition.
337+typedef struct {
338+ SWORD BootSec_JumpCmd; // Jump Command
339+ BYTE BootSec_OEMName[8]; // OEM name
340+ WORD BootSec_BPS; // Number of bytes per sector
341+ BYTE BootSec_SPC; // Number of sectors per cluster
342+ WORD BootSec_ResrvSec; // Number of reserved sectors at the beginning of the partition
343+ BYTE BootSec_FATCount; // Number of FATs on the partition
344+ WORD BootSec_RootDirEnts; // Number of root directory entries
345+ WORD BootSec_TotSec16; // Total number of sectors
346+ BYTE BootSec_MDesc; // Media descriptor
347+ WORD BootSec_SPF; // Number of sectors per FAT
348+ WORD BootSec_SPT; // Number of sectors per track
349+ WORD BootSec_HeadCnt; // Number of heads
350+ DWORD BootSec_HiddenSecCnt; // Number of hidden sectors
351+ DWORD BootSec_Reserved; // Reserved space
352+ BYTE BootSec_DriveNum; // Drive number
353+ BYTE BootSec_Reserved2; // Reserved space
354+ BYTE BootSec_BootSig; // Boot signature - equal to 0x29
355+ BYTE BootSec_VolID[4]; // Volume ID
356+ BYTE BootSec_VolLabel[11]; // Volume Label
357+ BYTE BootSec_FSType[8]; // File system type in ASCII. Not used for determination
358+#if defined __PIC32MX__ || defined __C30__
359+ } __attribute__ ((packed)) _BPB_FAT12;
360+#else
361+ } _BPB_FAT12;
362+#endif
363+
364+// Summary: A structure containing the bios parameter block for a FAT16 file system (in the boot sector)
365+// Description: The _BPB_FAT16 structure provides a layout of the "bios parameter block" in the boot sector of a FAT16 partition.
366+typedef struct {
367+ SWORD BootSec_JumpCmd; // Jump Command
368+ BYTE BootSec_OEMName[8]; // OEM name
369+ WORD BootSec_BPS; // Number of bytes per sector
370+ BYTE BootSec_SPC; // Number of sectors per cluster
371+ WORD BootSec_ResrvSec; // Number of reserved sectors at the beginning of the partition
372+ BYTE BootSec_FATCount; // Number of FATs on the partition
373+ WORD BootSec_RootDirEnts; // Number of root directory entries
374+ WORD BootSec_TotSec16; // Total number of sectors
375+ BYTE BootSec_MDesc; // Media descriptor
376+ WORD BootSec_SPF; // Number of sectors per FAT
377+ WORD BootSec_SPT; // Number of sectors per track
378+ WORD BootSec_HeadCnt; // Number of heads
379+ DWORD BootSec_HiddenSecCnt; // Number of hidden sectors
380+ DWORD BootSec_TotSec32; // Total sector count (32 bits)
381+ BYTE BootSec_DriveNum; // Drive number
382+ BYTE BootSec_Reserved; // Reserved space
383+ BYTE BootSec_BootSig; // Boot signature - equal to 0x29
384+ BYTE BootSec_VolID[4]; // Volume ID
385+ BYTE BootSec_VolLabel[11]; // Volume Label
386+ BYTE BootSec_FSType[8]; // File system type in ASCII. Not used for determination
387+#if defined __PIC32MX__ || defined __C30__
388+ } __attribute__ ((packed)) _BPB_FAT16;
389+#else
390+ } _BPB_FAT16;
391+#endif
392+
393+// Summary: A structure containing the bios parameter block for a FAT32 file system (in the boot sector)
394+// Description: The _BPB_FAT32 structure provides a layout of the "bios parameter block" in the boot sector of a FAT32 partition.
395+typedef struct {
396+ SWORD BootSec_jmpBoot; // Jump Command
397+ BYTE BootSec_OEMName[8]; // OEM name
398+ WORD BootSec_BytsPerSec; // Number of bytes per sector
399+ BYTE BootSec_SecPerClus; // Number of sectors per cluster
400+ WORD BootSec_RsvdSecCnt; // Number of reserved sectors at the beginning of the partition
401+ BYTE BootSec_NumFATs; // Number of FATs on the partition
402+ WORD BootSec_RootEntCnt; // Number of root directory entries
403+ WORD BootSec_TotSec16; // Total number of sectors
404+ BYTE BootSec_Media; // Media descriptor
405+ WORD BootSec_FATSz16; // Number of sectors per FAT
406+ WORD BootSec_SecPerTrk; // Number of sectors per track
407+ WORD BootSec_NumHeads; // Number of heads
408+ DWORD BootSec_HiddSec; // Number of hidden sectors
409+ DWORD BootSec_TotSec32; // Total sector count (32 bits)
410+ DWORD BootSec_FATSz32; // Sectors per FAT (32 bits)
411+ WORD BootSec_ExtFlags; // Presently active FAT. Defined by bits 0-3 if bit 7 is 1.
412+ WORD BootSec_FSVers; // FAT32 filesystem version. Should be 0:0
413+ DWORD BootSec_RootClus; // Start cluster of the root directory (should be 2)
414+ WORD BootSec_FSInfo; // File system information
415+ WORD BootSec_BkBootSec; // Backup boot sector address.
416+ BYTE BootSec_Reserved[12]; // Reserved space
417+ BYTE BootSec_DrvNum; // Drive number
418+ BYTE BootSec_Reserved1; // Reserved space
419+ BYTE BootSec_BootSig; // Boot signature - 0x29
420+ BYTE BootSec_VolID[4]; // Volume ID
421+ BYTE BootSec_VolLab[11]; // Volume Label
422+ BYTE BootSec_FilSysType[8]; // File system type in ASCII. Not used for determination
423+#if defined __PIC32MX__ || defined __C30__
424+ } __attribute__ ((packed)) _BPB_FAT32;
425+#else
426+ } _BPB_FAT32;
427+#endif
428+
429+
430+// Description: A macro for the boot sector bytes per sector value offset
431+#define BSI_BPS 11
432+
433+// Description: A macro for the boot sector sector per cluster value offset
434+#define BSI_SPC 13
435+
436+// Description: A macro for the boot sector reserved sector count value offset
437+#define BSI_RESRVSEC 14
438+
439+// Description: A macro for the boot sector FAT count value offset
440+#define BSI_FATCOUNT 16
441+
442+// Description: A macro for the boot sector root directory entry count value offset
443+#define BSI_ROOTDIRENTS 17
444+
445+// Description: A macro for the boot sector 16-bit total sector count value offset
446+#define BSI_TOTSEC16 19
447+
448+// Description: A macro for the boot sector sectors per FAT value offset
449+#define BSI_SPF 22
450+
451+// Description: A macro for the boot sector 32-bit total sector count value offset
452+#define BSI_TOTSEC32 32
453+
454+// Description: A macro for the boot sector boot signature offset
455+#define BSI_BOOTSIG 38
456+
457+// Description: A macro for the boot sector file system type string offset
458+#define BSI_FSTYPE 54
459+
460+// Description: A macro for the boot sector 32-bit sector per FAT value offset
461+#define BSI_FATSZ32 36
462+
463+// Description: A macro for the boot sector start cluster of root directory value offset
464+#define BSI_ROOTCLUS 44
465+
466+// Description: A macro for the FAT32 boot sector boot signature offset
467+#define BSI_FAT32_BOOTSIG 66
468+
469+// Description: A macro for the FAT32 boot sector file system type string offset
470+#define BSI_FAT32_FSTYPE 82
471+
472+
473+
474+// Summary: A partition table entry structure.
475+// Description: The PTE_MBR structure contains values found in a partition table entry in the MBR of a device.
476+typedef struct
477+{
478+ BYTE PTE_BootDes; // The boot descriptor (should be 0x00 in a non-bootable device)
479+ SWORD PTE_FrstPartSect; // The cylinder-head-sector address of the first sector of the partition
480+ BYTE PTE_FSDesc; // The file system descriptor
481+ SWORD PTE_LstPartSect; // The cylinder-head-sector address of the last sector of the partition
482+ DWORD PTE_FrstSect; // The logical block address of the first sector of the partition
483+ DWORD PTE_NumSect; // The number of sectors in a partition
484+#if defined __PIC32MX__ || defined __C30__
485+ } __attribute__ ((packed)) PTE_MBR;
486+#else
487+ } PTE_MBR;
488+#endif
489+
490+
491+// Summary: A structure of the organization of a master boot record.
492+// Description: The _PT_MBR structure has the same form as a master boot record. When the MBR is loaded from the device, it will
493+// be cast as a _PT_MBR structure so the MBR elements can be accessed.
494+typedef struct
495+{
496+ BYTE ConsChkRtn[446]; // Boot code
497+ PTE_MBR Partition0; // The first partition table entry
498+ PTE_MBR Partition1; // The second partition table entry
499+ PTE_MBR Partition2; // The third partition table entry
500+ PTE_MBR Partition3; // The fourth partition table entry
501+ BYTE Signature0; // MBR signature code - equal to 0x55
502+ BYTE Signature1; // MBR signature code - equal to 0xAA
503+#if defined __PIC32MX__ || defined __C30__
504+}__attribute__((packed)) _PT_MBR;
505+#else
506+}_PT_MBR;
507+#endif
508+
509+// Summary: A pointer to a _PT_MBR structure
510+// Description: The PT_MBR pointer points to a _PT_MBR structure.
511+typedef _PT_MBR * PT_MBR;
512+
513+
514+
515+// Summary: A structure of the organization of a boot sector.
516+// Description: The _BootSec structure has the same form as a boot sector. When the boot sector is loaded from the device, it will
517+// be cast as a _BootSec structure so the boot sector elements can be accessed.
518+typedef struct
519+{
520+ // A union of different bios parameter blocks
521+ union
522+ {
523+ _BPB_FAT32 FAT_32;
524+ _BPB_FAT16 FAT_16;
525+ _BPB_FAT12 FAT_12;
526+ }FAT;
527+ BYTE Reserved[512-sizeof(_BPB_FAT32)-2]; // Reserved space
528+ BYTE Signature0; // Boot sector signature code - equal to 0x55
529+ BYTE Signature1; // Boot sector signature code - equal to 0xAA
530+#if defined __PIC32MX__ || defined __C30__
531+ } __attribute__ ((packed)) _BootSec;
532+#else
533+ } _BootSec;
534+#endif
535+
536+// Summary: A pointer to a _BootSec structure
537+// Description: The BootSec pointer points to a _BootSec structure.
538+typedef _BootSec * BootSec;
539+
540+
541+
542+// Summary: A macro indicating the offset for the master boot record
543+// Description: FO_MBR is a macro that indicates the addresss of the master boot record on the device. When the device is initialized
544+// this sector will be read
545+#define FO_MBR 0L
546+
547+
548+
549+// Summary: A macro for the first boot sector/MBR signature byte
550+// 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
551+#define FAT_GOOD_SIGN_0 0x55
552+
553+// Summary: A macro for the second boot sector/MBR signature byte
554+// 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
555+#define FAT_GOOD_SIGN_1 0xAA
556+
557+
558+typedef struct
559+{
560+ BYTE errorCode;
561+ union
562+ {
563+ BYTE value;
564+ struct
565+ {
566+ BYTE sectorSize : 1;
567+ BYTE maxLUN : 1;
568+ } bits;
569+ } validityFlags;
570+
571+ WORD sectorSize;
572+ BYTE maxLUN;
573+} MEDIA_INFORMATION;
574+
575+typedef enum
576+{
577+ MEDIA_NO_ERROR, // No errors
578+ MEDIA_DEVICE_NOT_PRESENT, // The requested device is not present
579+ MEDIA_CANNOT_INITIALIZE // Cannot initialize media
580+} MEDIA_ERRORS;
581+
582+
583+
584+
585+/*******************************************************************/
586+/* Strunctures and defines */
587+/*******************************************************************/
588+
589+#ifndef FALSE
590+ // Summary: False value
591+ // Description: This macro will indicate that a condition is false.
592+ #define FALSE 0
593+#endif
594+#ifndef TRUE
595+ // Summary: True value
596+ // Description: This macro will indicate that a condition is true.
597+ #define TRUE !FALSE // True value
598+#endif
599+
600+
601+
602+
603+#ifndef SEEK_SET
604+ // Summary: Macro for the FSfseek SEEK_SET base location.
605+ // Description: Functions as an input for FSfseek that specifies that the position in the file will be changed
606+ // relative to the beginning of the file.
607+ #define SEEK_SET 0
608+
609+#endif
610+#ifndef SEEK_CUR
611+
612+ // Summary: Macro for the FSfseek SEEK_CUR base location.
613+ // Description: Functions as an input for FSfseek that specifies that the position in the file will be changed
614+ // relative to the current location of the file
615+ #define SEEK_CUR 1
616+
617+#endif
618+#ifndef SEEK_END
619+
620+ // Summary: Macro for the FSfseek SEEK_END base location
621+ // Description: Functions as an input for FSfseek that specifies that the position in the file will be changed
622+ // relative to the end of the file. For this macro, the offset value will be subtracted from
623+ // the end location of the file by default.
624+ #define SEEK_END 2
625+
626+#endif
627+
628+
629+
630+
631+// Summary: Macro for the FSfopen FS_APPEND mode
632+// Description: If this macro is specified as the mode argument in a call of FSfopen, the file being opened will
633+// be created if it doesn't exist. If it does exist, it's file information will be loaded and the
634+// current location in the file will be set to the end. The user will then be able to write to the file.
635+#define FS_APPEND "a"
636+#define APPEND "a" //deprecated
637+
638+// Summary: Macro for the FSfopen FS_WRITE mode
639+// Description: If this macro is specified as the mode argument in a call of FSfopen, the file being opened will
640+// be created if it doesn't exist. If it does exist, it will be erased and replaced by an empty file
641+// of the same name. The user will then be able to write to the file.
642+#define FS_WRITE "w"
643+#define WRITE "w" //deprecated
644+
645+// Summary: Macro for the FSfopen FS_READ mode
646+// Description: If this macro is specified as the mode argument in a call of FSfopen, the file information for the
647+// specified file will be loaded. If the file does not exist, the FSfopen function will fail. The user
648+// will then be able to read from the file.
649+#define FS_READ "r"
650+#if defined(__32MX795F512L__)
651+ #warning FSfopen must use "r" and not READ as input on this device
652+#else
653+ #define READ "r" //deprecated
654+#endif
655+
656+// Summary: Macro for the FSfopen FS_APPEND+ mode
657+// Description: If this macro is specified as the mode argument in a call of FSfopen, the file being opened will
658+// be created if it doesn't exist. If it does exist, it's file information will be loaded and the
659+// current location in the file will be set to the end. The user will then be able to write to the file
660+// or read from the file.
661+#define FS_APPENDPLUS "a+"
662+#define APPENDPLUS "a+" //deprecated
663+
664+// Summary: Macro for the FSfopen FS_WRITE+ mode
665+// Description: If this macro is specified as the mode argument in a call of FSfopen, the file being opened will
666+// be created if it doesn't exist. If it does exist, it will be erased and replaced by an empty file
667+// of the same name. The user will then be able to write to the file or read from the file.
668+#define FS_WRITEPLUS "w+"
669+#define WRITEPLUS "w+" //deprecated
670+
671+// Summary: Macro for the FSfopen FS_READ+ mode
672+// Description: If this macro is specified as the mode argument in a call of FSfopen, the file information for the
673+// specified file will be loaded. If the file does not exist, the FSfopen function will fail. The user
674+// will then be able to read from the file or write to the file.
675+#define FS_READPLUS "r+"
676+#define READPLUS "r+" //deprecated
677+
678+
679+
680+#ifndef intmax_t
681+ #ifdef __PIC24F__
682+ // Summary: A data type indicating the maximum integer size in an architecture
683+ // Description: The intmax_t data type refers to the maximum-sized data type on any given architecture. This
684+ // data type can be specified as a format specifier size specification for the FSfprintf function.
685+ #define intmax_t long long
686+ #elif defined __PIC24H__
687+ #define intmax_t long long
688+ #elif defined __dsPIC30F__
689+ #define intmax_t long long
690+ #elif defined __dsPIC33F__
691+ #define intmax_t long long
692+ #endif
693+#endif
694+
695+
696+
697+// Summary: Indicates flag conditions for a file object
698+// Description: The FILEFLAGS structure is used to indicate conditions in a file. It contains three flags: 'write' indicates
699+// that the file was opened in a mode that allows writes, 'read' indicates that the file was opened in a mode
700+// that allows reads, and 'FileWriteEOF' indicates that additional data that is written to the file will increase
701+// the file size.
702+typedef struct
703+{
704+ unsigned write :1; // Indicates a file was opened in a mode that allows writes
705+ unsigned read :1; // Indicates a file was opened in a mode that allows reads
706+ unsigned FileWriteEOF :1; // Indicates the current position in a file is at the end of the file
707+}FILEFLAGS;
708+
709+
710+
711+// Summary: Indicates how to search for file entries in the FILEfind function
712+// Description: The values in the SEARCH_TYPE enumeration are used internally by the library to indicate how the FILEfind function
713+// how to perform a search. The 'LOOK_FOR_EMPTY_ENTRY' value indicates that FILEfind should search for an empty file entry.
714+// The 'LOOK_FOR_MATCHING_ENTRY' value indicates that FILEfind should search for an entry that matches the FSFILE object
715+// that was passed into the FILEfind function.
716+typedef enum{
717+ LOOK_FOR_EMPTY_ENTRY = 0,
718+ LOOK_FOR_MATCHING_ENTRY
719+} SEARCH_TYPE;
720+
721+
722+
723+// Summary: Macro indicating the length of a 8.3 file name
724+// Description: The TOTAL_FILE_SIZE_8P3 macro indicates the maximum number of characters in an 8.3 file name. This value includes
725+// 8 characters for the name, three for the extentsion, and 1 for the radix ('.')
726+#define TOTAL_FILE_SIZE_8P3 (8+3+1)
727+#define TOTAL_FILE_SIZE TOTAL_FILE_SIZE_8P3
728+
729+// Summary: Macro indicating the max length of a LFN file name
730+// Description: The MAX_FILE_NAME_LENGTH_LFN macro indicates the maximum number of characters in an LFN file name.
731+#define MAX_FILE_NAME_LENGTH_LFN 256
732+
733+// Summary: A mask that indicates the limit of directory entries in a sector
734+// Description: The MASK_MAX_FILE_ENTRY_LIMIT_BITS is used to indicate to the Cache_File_Entry function that a new sector needs to
735+// be loaded.
736+#define MASK_MAX_FILE_ENTRY_LIMIT_BITS 0x0f
737+
738+// Summary: Value used for shift operations to calculate the sector offset in a directory
739+// Description: The VALUE_BASED_ON_ENTRIES_PER_CLUSTER macro is used to calculate sector offsets for directories. The position of the
740+// entry is shifted by 4 bits (divided by 16, since there are 16 entries in a sector) to calculate how many sectors a
741+// specified entry is offset from the beginning of the directory.
742+#define VALUE_BASED_ON_ENTRIES_PER_CLUSTER 4
743+
744+// Summary: A value that will indicate that a dotdot directory entry points to the root.
745+// Description: The VALUE_DOTDOT_CLUSTER_VALUE_FOR_ROOT macro is used as an absolute address when writing information to a dotdot entry
746+// in a newly created directory. If a dotdot entry points to the root directory, it's cluster value must be set to 0,
747+// regardless of the actual cluster number of the root directory.
748+#define VALUE_DOTDOT_CLUSTER_VALUE_FOR_ROOT 0
749+
750+// Summary: MAcro indicating the length of an 8.3 file name in a directory entry
751+// Description: The FILE_NAME_SIZE_8P3 macro indicates the number of characters that an 8.3 file name will take up when packed in
752+// a directory entry. This value includes 8 characters for the name and 3 for the extension. Note that the radix is not
753+// stored in the directory entry.
754+#define FILE_NAME_SIZE_8P3 11
755+#define FILE_NAME_SIZE FILE_NAME_SIZE_8P3
756+
757+
758+// Summary: Contains file information and is used to indicate which file to access.
759+// Description: The FSFILE structure is used to hold file information for an open file as it's being modified or accessed. A pointer to
760+// an open file's FSFILE structure will be passeed to any library function that will modify that file.
761+typedef struct
762+{
763+ DISK * dsk; // Pointer to a DISK structure
764+ DWORD cluster; // The first cluster of the file
765+ DWORD ccls; // The current cluster of the file
766+ WORD sec; // The current sector in the current cluster of the file
767+ WORD pos; // The position in the current sector
768+ DWORD seek; // The absolute position in the file
769+ DWORD size; // The size of the file
770+ FILEFLAGS flags; // A structure containing file flags
771+ WORD time; // The file's last update time
772+ WORD date; // The file's last update date
773+ char name[FILE_NAME_SIZE_8P3]; // The short name of the file
774+ #ifdef SUPPORT_LFN
775+ BOOL AsciiEncodingType; // Ascii file name or Non-Ascii file name indicator
776+ unsigned short int *utf16LFNptr; // Pointer to long file name in UTF16 format
777+ unsigned short int utf16LFNlength; // LFN length in terms of words including the NULL word at the last.
778+ #endif
779+ WORD entry; // The position of the file's directory entry in it's directory
780+ WORD chk; // File structure checksum
781+ WORD attributes; // The file attributes
782+ DWORD dirclus; // The base cluster of the file's directory
783+ DWORD dirccls; // The current cluster of the file's directory
784+} FSFILE;
785+
786+/* Summary: Possible results of the FSGetDiskProperties() function.
787+** Description: See the FSGetDiskProperties() function for more information.
788+*/
789+typedef enum
790+{
791+ FS_GET_PROPERTIES_NO_ERRORS = 0,
792+ FS_GET_PROPERTIES_DISK_NOT_MOUNTED,
793+ FS_GET_PROPERTIES_CLUSTER_FAILURE,
794+ FS_GET_PROPERTIES_STILL_WORKING = 0xFF
795+} FS_DISK_ERRORS;
796+
797+
798+/* Summary: Contains the disk search information, intermediate values, and results
799+** Description: This structure is used in conjunction with the FSGetDiskProperties()
800+** function. See that function for more information about the usage.
801+*/
802+typedef struct
803+{
804+ DISK * disk; /* pointer to the disk we are searching */
805+ BOOL new_request; /* is this a new request or a continued request */
806+ FS_DISK_ERRORS properties_status; /* status of the last call of the function */
807+
808+ struct
809+ {
810+ BYTE disk_format; /* disk format: FAT12, FAT16, FAT32 */
811+ WORD sector_size; /* sector size of the drive */
812+ BYTE sectors_per_cluster; /* number of sectors per cluster */
813+ DWORD total_clusters; /* the number of total clusters on the drive */
814+ DWORD free_clusters; /* the number of free (unused) clusters on drive */
815+ } results; /* the results of the current search */
816+
817+ struct
818+ {
819+ DWORD c;
820+ DWORD curcls;
821+ DWORD EndClusterLimit;
822+ DWORD ClusterFailValue;
823+ } private; /* intermediate values used to continue searches. This
824+ member should be used only by the FSGetDiskProperties()
825+ function */
826+
827+} FS_DISK_PROPERTIES;
828+
829+// Summary: A structure used for searching for files on a device.
830+// Description: The SearchRec structure is used when searching for file on a device. It contains parameters that will be loaded with
831+// file information when a file is found. It also contains the parameters that the user searched for, allowing further
832+// searches to be perfomed in the same directory for additional files that meet the specified criteria.
833+typedef struct
834+{
835+ char filename[FILE_NAME_SIZE_8P3 + 2]; // The name of the file that has been found
836+ unsigned char attributes; // The attributes of the file that has been found
837+ unsigned long filesize; // The size of the file that has been found
838+ unsigned long timestamp; // The last modified time of the file that has been found (create time for directories)
839+ #ifdef SUPPORT_LFN
840+ BOOL AsciiEncodingType; // Ascii file name or Non-Ascii file name indicator
841+ unsigned short int *utf16LFNfound; // Pointer to long file name found in UTF16 format
842+ unsigned short int utf16LFNfoundLength; // LFN Found length in terms of words including the NULL word at the last.
843+ #endif
844+ unsigned int entry; // The directory entry of the last file found that matches the specified attributes. (Internal use only)
845+ char searchname[FILE_NAME_SIZE_8P3 + 2]; // The 8.3 format name specified when the user began the search. (Internal use only)
846+ unsigned char searchattr; // The attributes specified when the user began the search. (Internal use only)
847+ unsigned long cwdclus; // The directory that this search was performed in. (Internal use only)
848+ unsigned char initialized; // Check to determine if the structure was initialized by FindFirst (Internal use only)
849+} SearchRec;
850+
851+
852+/***************************************************************************
853+* Prototypes *
854+***************************************************************************/
855+
856+
857+
858+
859+/*************************************************************************
860+ Function:
861+ int FSInit(void)
862+ Summary:
863+ Function to initialize the device.
864+ Conditions:
865+ The physical device should be connected to the microcontroller.
866+ Input:
867+ None
868+ Return Values:
869+ TRUE - Initialization successful
870+ FALSE - Initialization unsuccessful
871+ Side Effects:
872+ The FSerrno variable will be changed.
873+ Description:
874+ Initializes the static or dynamic memory slots for holding file
875+ structures. Initializes the device with the DISKmount function. Loads
876+ MBR and boot sector information. Initializes the current working
877+ directory to the root directory for the device if directory support
878+ is enabled.
879+ Remarks:
880+ None
881+ *************************************************************************/
882+
883+int FSInit(void);
884+
885+
886+/*********************************************************************
887+ Function:
888+ FSFILE * FSfopen (const char * fileName, const char *mode)
889+ Summary:
890+ Open a Ascii file
891+ Conditions:
892+ For read modes, file exists; FSInit performed
893+ Input:
894+ fileName - The name of the file to open
895+ mode -
896+ - WRITE - Create a new file or replace an existing file
897+ - READ - Read data from an existing file
898+ - APPEND - Append data to an existing file
899+ - WRITEPLUS - Create a new file or replace an existing file (reads also enabled)
900+ - READPLUS - Read data from an existing file (writes also enabled)
901+ - APPENDPLUS - Append data to an existing file (reads also enabled)
902+ Return Values:
903+ FSFILE * - The pointer to the file object
904+ NULL - The file could not be opened
905+ Side Effects:
906+ The FSerrno variable will be changed.
907+ Description:
908+ This function will open a file or directory. First, RAM in the
909+ dynamic heap or static array will be allocated to a new FSFILE object.
910+ Then, the specified file name will be formatted to ensure that it's
911+ in 8.3 format or LFN format. Next, the FILEfind function will be used
912+ to search for the specified file name. If the name is found, one of three
913+ things will happen: if the file was opened in read mode, its file
914+ info will be loaded using the FILEopen function; if it was opened in
915+ write mode, it will be erased, and a new file will be constructed in
916+ its place; if it was opened in append mode, its file info will be
917+ loaded with FILEopen and the current location will be moved to the
918+ end of the file using the FSfseek function. If the file was not
919+ found by FILEfind, a new file will be created if the mode was specified as
920+ a write or append mode. In these cases, a pointer to the heap or
921+ static FSFILE object array will be returned. If the file was not
922+ found and the mode was specified as a read mode, the memory
923+ allocated to the file will be freed and the NULL pointer value
924+ will be returned.
925+ Remarks:
926+ None.
927+ *********************************************************************/
928+
929+FSFILE * FSfopen(const char * fileName, const char *mode);
930+
931+#ifdef SUPPORT_LFN
932+/*********************************************************************
933+ Function:
934+ FSFILE * wFSfopen (const unsigned short int * fileName, const char *mode)
935+ Summary:
936+ Open a UTF16 file.
937+ Conditions:
938+ For read modes, file exists; FSInit performed
939+ Input:
940+ fileName - The name of the file to open
941+ mode -
942+ - WRITE - Create a new file or replace an existing file
943+ - READ - Read data from an existing file
944+ - APPEND - Append data to an existing file
945+ - WRITEPLUS - Create a new file or replace an existing file (reads also enabled)
946+ - READPLUS - Read data from an existing file (writes also enabled)
947+ - APPENDPLUS - Append data to an existing file (reads also enabled)
948+ Return Values:
949+ FSFILE * - The pointer to the file object
950+ NULL - The file could not be opened
951+ Side Effects:
952+ The FSerrno variable will be changed.
953+ Description:
954+ This function will open a file or directory. First, RAM in the
955+ dynamic heap or static array will be allocated to a new FSFILE object.
956+ Then, the specified file name will be formatted to ensure that it's
957+ in 8.3 format or LFN format. Next, the FILEfind function will be used
958+ to search for the specified file name. If the name is found, one of three
959+ things will happen: if the file was opened in read mode, its file
960+ info will be loaded using the FILEopen function; if it was opened in
961+ write mode, it will be erased, and a new file will be constructed in
962+ its place; if it was opened in append mode, its file info will be
963+ loaded with FILEopen and the current location will be moved to the
964+ end of the file using the FSfseek function. If the file was not
965+ found by FILEfind, a new file will be created if the mode was specified as
966+ a write or append mode. In these cases, a pointer to the heap or
967+ static FSFILE object array will be returned. If the file was not
968+ found and the mode was specified as a read mode, the memory
969+ allocated to the file will be freed and the NULL pointer value
970+ will be returned.
971+ Remarks:
972+ None.
973+ *********************************************************************/
974+
975+FSFILE * wFSfopen(const unsigned short int * fileName, const char *mode);
976+#endif
977+
978+#ifdef ALLOW_PGMFUNCTIONS
979+
980+/******************************************************************************
981+ Function:
982+ FSFILE * FSfopenpgm(const rom char * fileName, const rom char *mode)
983+ Summary:
984+ Open a Ascii file named with a ROM string on PIC18
985+ Conditions:
986+ For read modes, file exists; FSInit performed
987+ Input:
988+ fileName - The name of the file to be opened (ROM)
989+ mode - The mode the file will be opened in (ROM)
990+ Return Values:
991+ FSFILE * - A pointer to the file object
992+ NULL - File could not be opened
993+ Side Effects:
994+ The FSerrno variable will be changed.
995+ Description:
996+ The FSfopenpgm function will copy a PIC18 ROM fileName and mode argument
997+ into RAM arrays, and then pass those arrays to the FSfopen function.
998+ Remarks:
999+ This function is for use with PIC18 when passing arguments in ROM.
1000+ ******************************************************************************/
1001+
1002+ FSFILE * FSfopenpgm(const rom char * fileName, const rom char *mode);
1003+
1004+
1005+/**************************************************************************************
1006+ Function:
1007+ int FindFirstpgm (const char * fileName, unsigned int attr, SearchRec * rec)
1008+ Summary:
1009+ Find a file named with a ROM string on PIC18
1010+ Conditions:
1011+ None
1012+ Input:
1013+ fileName - The name of the file to be found (ROM)
1014+ attr - The attributes of the file to be found
1015+ rec - Pointer to a search record to store the file info in
1016+ Return Values:
1017+ 0 - File was found
1018+ -1 - No file matching the given parameters was found
1019+ Side Effects:
1020+ Search criteria from previous FindFirstpgm call on passed SearchRec object
1021+ will be lost.The FSerrno variable will be changed.
1022+ Description:
1023+ The FindFirstpgm function will copy a PIC18 ROM fileName argument
1024+ into a RAM array, and then pass that array to the FindFirst function.
1025+ Remarks:
1026+ Call FindFirstpgm or FindFirst before calling FindNext.
1027+ This function is for use with PIC18 when passing arguments in ROM.
1028+ **************************************************************************************/
1029+
1030+ int FindFirstpgm (const rom char * fileName, unsigned int attr, SearchRec * rec);
1031+
1032+
1033+/**************************************************************************
1034+ Function:
1035+ int FSchdirpgm (const rom char * path)
1036+ Summary:
1037+ Changed the CWD with a path in ROM on PIC18
1038+ Conditions:
1039+ None
1040+ Input:
1041+ path - The path of the directory to change to (ROM)
1042+ Return Values:
1043+ 0 - The current working directory was changed successfully
1044+ EOF - The current working directory could not be changed
1045+ Side Effects:
1046+ The current working directory may be changed. The FSerrno variable will
1047+ be changed.
1048+ Description:
1049+ The FSchdirpgm function passes a PIC18 ROM path pointer to the
1050+ chdirhelper function.
1051+ Remarks:
1052+ This function is for use with PIC18 when passing arguments in ROM
1053+ **************************************************************************/
1054+
1055+ int FSchdirpgm (const rom char * path);
1056+
1057+ #ifdef ALLOW_WRITES
1058+
1059+
1060+/*************************************************************
1061+ Function:
1062+ int FSremovepgm (const rom char * fileName)
1063+ Summary:
1064+ Delete a file named with a ROM string on PIC18
1065+ Conditions:
1066+ File not opened; file exists
1067+ Input:
1068+ fileName - The name of the file to be deleted (ROM)
1069+ Return Values:
1070+ 0 - File was removed successfully
1071+ -1 - File could not be removed
1072+ Side Effects:
1073+ The FSerrno variable will be changed.
1074+ Description:
1075+ The FSremovepgm function will copy a PIC18 ROM fileName argument
1076+ into a RAM array, and then pass that array to the FSremove function.
1077+ Remarks:
1078+ This function is for use with PIC18 when passing arguments in ROM.
1079+ *************************************************************/
1080+
1081+ int FSremovepgm (const rom char * fileName);
1082+
1083+
1084+/**************************************************************************
1085+ Function:
1086+ int FSmkdirpgm (const rom char * path)
1087+ Summary:
1088+ Create a directory with a path in ROM on PIC18
1089+ Conditions:
1090+ None
1091+ Input:
1092+ path - The path of directories to create (ROM)
1093+ Return Values:
1094+ 0 - The specified directory was created successfully
1095+ EOF - The specified directory could not be created
1096+ Side Effects:
1097+ Will create all non-existent directories in the path. The FSerrno
1098+ variable will be changed.
1099+ Description:
1100+ The FSmkdirpgm function passes a PIC18 ROM path pointer to the
1101+ mkdirhelper function.
1102+ Remarks:
1103+ This function is for use with PIC18 when passing arugments in ROM
1104+ **************************************************************************/
1105+
1106+ int FSmkdirpgm (const rom char * path);
1107+
1108+
1109+/**************************************************************************
1110+ Function:
1111+ int FSrmdirpgm (const rom char * path)
1112+ Summary:
1113+ Delete a directory with a path in ROM on PIC18
1114+ Conditions:
1115+ None.
1116+ Input:
1117+ path - The path of the directory to remove (ROM)
1118+ rmsubdirs -
1119+ - TRUE - All sub-dirs and files in the target dir will be removed
1120+ - FALSE - FSrmdir will not remove non-empty directories
1121+ Return Values:
1122+ 0 - The specified directory was deleted successfully
1123+ EOF - The specified directory could not be deleted
1124+ Side Effects:
1125+ The FSerrno variable will be changed.
1126+ Description:
1127+ The FSrmdirpgm function passes a PIC18 ROM path pointer to the
1128+ rmdirhelper function.
1129+ Remarks:
1130+ This function is for use with PIC18 when passing arguments in ROM.
1131+ **************************************************************************/
1132+
1133+ int FSrmdirpgm (const rom char * path, unsigned char rmsubdirs);
1134+
1135+
1136+/*****************************************************************
1137+ Function:
1138+ int FSrenamepgm(const rom char * fileName, FSFILE * fo)
1139+ Summary:
1140+ Rename a file named with a ROM string on PIC18
1141+ Conditions:
1142+ File opened.
1143+ Input:
1144+ fileName - The new name of the file (in ROM)
1145+ fo - The file to rename
1146+ Return Values:
1147+ 0 - File renamed successfully
1148+ -1 - File could not be renamed
1149+ Side Effects:
1150+ The FSerrno variable will be changed.
1151+ Description:
1152+ The Fsrenamepgm function will copy the rom fileName specified
1153+ by the user into a RAM array and pass that array into the
1154+ FSrename function.
1155+ Remarks:
1156+ This function is for use with PIC18 when passing arguments in ROM.
1157+ *****************************************************************/
1158+
1159+ int FSrenamepgm (const rom char * fileName, FSFILE * fo);
1160+ #endif
1161+#endif
1162+
1163+
1164+/************************************************************
1165+ Function:
1166+ int FSfclose(FSFILE *fo)
1167+ Summary:
1168+ Update file information and free FSFILE objects
1169+ Conditions:
1170+ File opened
1171+ Input:
1172+ fo - Pointer to the file to close
1173+ Return Values:
1174+ 0 - File closed successfully
1175+ EOF - Error closing the file
1176+ Side Effects:
1177+ The FSerrno variable will be changed.
1178+ Description:
1179+ This function will update the directory entry for the
1180+ file pointed to by 'fo' with the information contained
1181+ in 'fo,' including the new file size and attributes.
1182+ Timestamp information will also be loaded based on the
1183+ method selected by the user and written to the entry
1184+ as the last modified time and date. The file entry will
1185+ then be written to the device. Finally, the memory
1186+ used for the specified file object will be freed from
1187+ the dynamic heap or the array of FSFILE objects.
1188+ Remarks:
1189+ A function to flush data to the device without closing the
1190+ file can be created by removing the portion of this
1191+ function that frees the memory and the line that clears
1192+ the write flag.
1193+ ************************************************************/
1194+
1195+int FSfclose(FSFILE *fo);
1196+
1197+
1198+/*********************************************************
1199+ Function:
1200+ void FSrewind (FSFILE * fo)
1201+ Summary:
1202+ Set the current position in a file to the beginning
1203+ Conditions:
1204+ File opened.
1205+ Input:
1206+ fo - Pointer to file structure
1207+ Return Values:
1208+ None
1209+ Side Effects:
1210+ None.
1211+ Description:
1212+ The FSrewind funciton will reset the position of the
1213+ specified file to the beginning of the file. This
1214+ functionality is faster than using FSfseek to reset
1215+ the position in the file.
1216+ Remarks:
1217+ None.
1218+ *********************************************************/
1219+
1220+void FSrewind (FSFILE *fo);
1221+
1222+
1223+/**************************************************************************
1224+ Function:
1225+ size_t FSfread(void *ptr, size_t size, size_t n, FSFILE *stream)
1226+ Summary:
1227+ Read data from a file
1228+ Conditions:
1229+ File is opened in a read mode
1230+ Input:
1231+ ptr - Destination buffer for read bytes
1232+ size - Size of units in bytes
1233+ n - Number of units to be read
1234+ stream - File to be read from
1235+ Return:
1236+ size_t - number of units read
1237+ Side Effects:
1238+ The FSerrno variable will be changed.
1239+ Description:
1240+ The FSfread function will read data from the specified file. First,
1241+ the appropriate sector of the file is loaded. Then, data is read into
1242+ the specified buffer until the specified number of bytes have been read.
1243+ When a cluster boundary is reached, a new cluster will be loaded. The
1244+ parameters 'size' and 'n' indicate how much data to read. 'Size'
1245+ refers to the size of one object to read (in bytes), and 'n' will refer
1246+ to the number of these objects to read. The value returned will be equal
1247+ to 'n' unless an error occured or the user tried to read beyond the end
1248+ of the file.
1249+ Remarks:
1250+ None.
1251+ **************************************************************************/
1252+
1253+size_t FSfread(void *ptr, size_t size, size_t n, FSFILE *stream);
1254+
1255+
1256+/**********************************************************************
1257+ Function:
1258+ int FSfseek(FSFILE *stream, long offset, int whence)
1259+ Summary:
1260+ Change the current position in a file
1261+ Conditions:
1262+ File opened
1263+ Input:
1264+ stream - Pointer to file structure
1265+ offset - Offset from base location
1266+ whence -
1267+ - SEEK_SET - Seek from start of file
1268+ - SEEK_CUR - Seek from current location
1269+ - SEEK_END - Seek from end of file (subtract offset)
1270+ Return Values:
1271+ 0 - Operation successful
1272+ -1 - Operation unsuccesful
1273+ Side Effects:
1274+ The FSerrno variable will be changed.
1275+ Description:
1276+ The FSfseek function will change the current position in the file to
1277+ one specified by the user. First, an absolute offset is calculated
1278+ using the offset and base location passed in by the user. Then, the
1279+ position variables are updated, and the sector number that corresponds
1280+ to the new location. That sector is then loaded. If the offset
1281+ falls exactly on a cluster boundary, a new cluster will be allocated
1282+ to the file and the position will be set to the first byte of that
1283+ cluster.
1284+ Remarks:
1285+ None
1286+ **********************************************************************/
1287+
1288+int FSfseek(FSFILE *stream, long offset, int whence);
1289+
1290+
1291+/*******************************************************************
1292+ Function:
1293+ long FSftell (FSFILE * fo)
1294+ Summary:
1295+ Determine the current location in a file
1296+ Conditions:
1297+ File opened
1298+ Input:
1299+ fo - Pointer to file structure
1300+ Return: Current location in the file
1301+ Side Effects:
1302+ The FSerrno variable will be changed
1303+ Description:
1304+ The FSftell function will return the current position in the
1305+ file pointed to by 'fo' by returning the 'seek' variable in the
1306+ FSFILE object, which is used to keep track of the absolute
1307+ location of the current position in the file.
1308+ Remarks:
1309+ None
1310+ *******************************************************************/
1311+
1312+long FSftell(FSFILE *fo);
1313+
1314+
1315+/****************************************************
1316+ Function:
1317+ int FSfeof( FSFILE * stream )
1318+ Summary:
1319+ Indicate whether the current file position is at the end
1320+ Conditions:
1321+ File is open in a read mode
1322+ Input:
1323+ stream - Pointer to the target file
1324+ Return Values:
1325+ Non-Zero - EOF reached
1326+ 0 - Not at end of File
1327+ Side Effects:
1328+ The FSerrno variable will be changed.
1329+ Description:
1330+ The FSfeof function will indicate that the end-of-
1331+ file has been reached for the specified file by
1332+ comparing the absolute location in the file to the
1333+ size of the file.
1334+ Remarks:
1335+ None.
1336+ ****************************************************/
1337+
1338+int FSfeof( FSFILE * stream );
1339+
1340+
1341+#ifdef ALLOW_FORMATS
1342+/*******************************************************************
1343+ Function:
1344+ int FSformat (char mode, long int serialNumber, char * volumeID)
1345+ Summary:
1346+ Formats a device
1347+ Conditions:
1348+ The device must possess a valid master boot record.
1349+ Input:
1350+ mode - - 0 - Just erase the FAT and root
1351+ - 1 - Create a new boot sector
1352+ serialNumber - Serial number to write to the card
1353+ volumeID - Name of the card
1354+ Return Values:
1355+ 0 - Format was successful
1356+ EOF - Format was unsuccessful
1357+ Side Effects:
1358+ The FSerrno variable will be changed.
1359+ Description:
1360+ The FSformat function can be used to create a new boot sector
1361+ on a device, based on the information in the master boot record.
1362+ This function will first initialize the I/O pins and the device,
1363+ and then attempts to read the master boot record. If the MBR
1364+ cannot be loaded successfully, the function will fail. Next, if
1365+ the 'mode' argument is specified as '0' the existing boot sector
1366+ information will be loaded. If the 'mode' argument is '1' an
1367+ entirely new boot sector will be constructed using the disk
1368+ values from the master boot record. Once the boot sector has
1369+ been successfully loaded/created, the locations of the FAT and
1370+ root will be loaded from it, and they will be completely
1371+ erased. If the user has specified a volumeID parameter, a
1372+ VOLUME attribute entry will be created in the root directory
1373+ to name the device.
1374+
1375+ FAT12, FAT16 and FAT32 formatting are supported.
1376+
1377+ Based on the number of sectors, the format function automatically
1378+ compute the smallest possible value for the cluster size in order to
1379+ accommodate the physical size of the media. In this case, if a media
1380+ with a big capacity is formatted, the format function may take a very
1381+ long time to write all the FAT tables.
1382+
1383+ Therefore, the FORMAT_SECTORS_PER_CLUSTER macro may be used to
1384+ specify the exact cluster size (in multiples of sector size). This
1385+ macro can be defined in FSconfig.h
1386+
1387+ Remarks:
1388+ Only devices with a sector size of 512 bytes are supported by the
1389+ format function
1390+ *******************************************************************/
1391+
1392+int FSformat (char mode, long int serialNumber, char * volumeID);
1393+#endif
1394+
1395+
1396+#ifdef ALLOW_WRITES
1397+/***************************************************************************
1398+ Function:
1399+ int FSattrib (FSFILE * file, unsigned char attributes)
1400+ Summary:
1401+ Change the attributes of a file
1402+ Conditions:
1403+ File opened
1404+ Input:
1405+ file - Pointer to file structure
1406+ attributes - The attributes to set for the file
1407+ - Attribute - Value - Indications
1408+ - ATTR_READ_ONLY - 0x01 - The read-only attribute
1409+ - ATTR_HIDDEN - 0x02 - The hidden attribute
1410+ - ATTR_SYSTEM - 0x04 - The system attribute
1411+ - ATTR_ARCHIVE - 0x20 - The archive attribute
1412+ Return Values:
1413+ 0 - Attribute change was successful
1414+ -1 - Attribute change was unsuccessful
1415+ Side Effects:
1416+ The FSerrno variable will be changed.
1417+ Description:
1418+ The FSattrib funciton will set the attributes of the specified file
1419+ to the attributes passed in by the user. This function will load the
1420+ file entry, replace the attributes with the ones specified, and write
1421+ the attributes back. If the specified file is a directory, the
1422+ directory attribute will be preserved.
1423+ Remarks:
1424+ None
1425+ ***************************************************************************/
1426+
1427+int FSattrib (FSFILE * file, unsigned char attributes);
1428+
1429+
1430+/***************************************************************
1431+ Function:
1432+ int FSrename (const rom char * fileName, FSFILE * fo)
1433+ Summary:
1434+ Change the Ascii name of a file or directory
1435+ Conditions:
1436+ File opened.
1437+ Input:
1438+ fileName - The new name of the file
1439+ fo - The file to rename
1440+ Return Values:
1441+ 0 - File was renamed successfully
1442+ EOF - File was not renamed
1443+ Side Effects:
1444+ The FSerrno variable will be changed.
1445+ Description:
1446+ The FSrename function will rename a file. First, it will
1447+ search through the current working directory to ensure the
1448+ specified new filename is not already in use. If it isn't,
1449+ the new filename will be written to the file entry of the
1450+ file pointed to by 'fo.'
1451+ Remarks:
1452+ None
1453+ ***************************************************************/
1454+
1455+int FSrename (const char * fileName, FSFILE * fo);
1456+
1457+#ifdef SUPPORT_LFN
1458+/***************************************************************
1459+ Function:
1460+ int wFSrename (const rom unsigned short int * fileName, FSFILE * fo)
1461+ Summary:
1462+ Change the name of a file or directory to the UTF16 input fileName
1463+ Conditions:
1464+ File opened.
1465+ Input:
1466+ fileName - The new name of the file
1467+ fo - The file to rename
1468+ Return Values:
1469+ 0 - File was renamed successfully
1470+ EOF - File was not renamed
1471+ Side Effects:
1472+ The FSerrno variable will be changed.
1473+ Description:
1474+ The wFSrename function will rename a file. First, it will
1475+ search through the current working directory to ensure the
1476+ specified new UTF16 filename is not already in use. If it isn't,
1477+ the new filename will be written to the file entry of the
1478+ file pointed to by 'fo.'
1479+ Remarks:
1480+ None
1481+ ***************************************************************/
1482+
1483+int wFSrename (const unsigned short int * fileName, FSFILE * fo);
1484+#endif
1485+
1486+/*********************************************************************
1487+ Function:
1488+ int FSremove (const char * fileName)
1489+ Summary:
1490+ Delete a Ascii file
1491+ Conditions:
1492+ File not opened, file exists
1493+ Input:
1494+ fileName - Name of the file to erase
1495+ Return Values:
1496+ 0 - File removed
1497+ EOF - File was not removed
1498+ Side Effects:
1499+ The FSerrno variable will be changed.
1500+ Description:
1501+ The FSremove function will attempt to find the specified file with
1502+ the FILEfind function. If the file is found, it will be erased
1503+ using the FILEerase function.The user can also provide ascii alias name
1504+ of the ascii long file name as the input to this function to get it erased
1505+ from the memory.
1506+ Remarks:
1507+ None
1508+ **********************************************************************/
1509+
1510+int FSremove (const char * fileName);
1511+
1512+#ifdef SUPPORT_LFN
1513+/*********************************************************************
1514+ Function:
1515+ int wFSremove (const unsigned short int * fileName)
1516+ Summary:
1517+ Delete a UTF16 file
1518+ Conditions:
1519+ File not opened, file exists
1520+ Input:
1521+ fileName - Name of the file to erase
1522+ Return Values:
1523+ 0 - File removed
1524+ EOF - File was not removed
1525+ Side Effects:
1526+ The FSerrno variable will be changed.
1527+ Description:
1528+ The wFSremove function will attempt to find the specified UTF16 file
1529+ name with the FILEfind function. If the file is found, it will be erased
1530+ using the FILEerase function.
1531+ Remarks:
1532+ None
1533+ **********************************************************************/
1534+
1535+int wFSremove (const unsigned short int * fileName);
1536+#endif
1537+
1538+/*********************************************************************************
1539+ Function:
1540+ size_t FSfwrite(const void *data_to_write, size_t size, size_t n, FSFILE *stream)
1541+ Summary:
1542+ Write data to a file
1543+ Conditions:
1544+ File opened in WRITE, APPEND, WRITE+, APPEND+, READ+ mode
1545+ Input:
1546+ data_to_write - Pointer to source buffer
1547+ size - Size of units in bytes
1548+ n - Number of units to transfer
1549+ stream - Pointer to file structure
1550+ Return:
1551+ size_t - number of units written
1552+ Side Effects:
1553+ The FSerrno variable will be changed.
1554+ Description:
1555+ The FSfwrite function will write data to a file. First, the sector that
1556+ corresponds to the current position in the file will be loaded (if it hasn't
1557+ already been cached in the global data buffer). Data will then be written to
1558+ the device from the specified buffer until the specified amount has been written.
1559+ If the end of a cluster is reached, the next cluster will be loaded, unless
1560+ the end-of-file flag for the specified file has been set. If it has, a new
1561+ cluster will be allocated to the file. Finally, the new position and filesize
1562+ will be stored in the FSFILE object. The parameters 'size' and 'n' indicate how
1563+ much data to write. 'Size' refers to the size of one object to write (in bytes),
1564+ and 'n' will refer to the number of these objects to write. The value returned
1565+ will be equal to 'n' unless an error occured.
1566+ Remarks:
1567+ None.
1568+ *********************************************************************************/
1569+
1570+size_t FSfwrite(const void *data_to_write, size_t size, size_t n, FSFILE *stream);
1571+
1572+#endif
1573+
1574+#ifdef ALLOW_DIRS
1575+
1576+
1577+/**************************************************************************
1578+ Function:
1579+ int FSchdir (char * path)
1580+ Summary:
1581+ Change the current working directory as per the path specified in Ascii format
1582+ Conditions:
1583+ None
1584+ Input:
1585+ path - The path of the directory to change to.
1586+ Return Values:
1587+ 0 - The current working directory was changed successfully
1588+ EOF - The current working directory could not be changed
1589+ Side Effects:
1590+ The current working directory may be changed. The FSerrno variable will
1591+ be changed.
1592+ Description:
1593+ The FSchdir function passes a RAM pointer to the path to the
1594+ chdirhelper function.
1595+ Remarks:
1596+ None
1597+ **************************************************************************/
1598+
1599+int FSchdir (char * path);
1600+
1601+#ifdef SUPPORT_LFN
1602+/**************************************************************************
1603+ Function:
1604+ int wFSchdir (unsigned short int * path)
1605+ Summary:
1606+ Change the current working directory as per the path specified in UTF16 format
1607+ Conditions:
1608+ None
1609+ Input:
1610+ path - The path of the directory to change to.
1611+ Return Values:
1612+ 0 - The current working directory was changed successfully
1613+ EOF - The current working directory could not be changed
1614+ Side Effects:
1615+ The current working directory may be changed. The FSerrno variable will
1616+ be changed.
1617+ Description:
1618+ The FSchdir function passes a RAM pointer to the path to the
1619+ chdirhelper function.
1620+ Remarks:
1621+ None
1622+ **************************************************************************/
1623+
1624+int wFSchdir (unsigned short int * path);
1625+#endif
1626+
1627+/**************************************************************
1628+ Function:
1629+ char * FSgetcwd (char * path, int numchars)
1630+ Summary:
1631+ Get the current working directory path in Ascii format
1632+ Conditions:
1633+ None
1634+ Input:
1635+ path - Pointer to the array to return the cwd name in
1636+ numchars - Number of chars in the path
1637+ Return Values:
1638+ char * - The cwd name string pointer (path or defaultArray)
1639+ NULL - The current working directory name could not be loaded.
1640+ Side Effects:
1641+ The FSerrno variable will be changed
1642+ Description:
1643+ The FSgetcwd function will get the name of the current
1644+ working directory and return it to the user. The name
1645+ will be copied into the buffer pointed to by 'path,'
1646+ starting at the root directory and copying as many chars
1647+ as possible before the end of the buffer. The buffer
1648+ size is indicated by the 'numchars' argument. The first
1649+ thing this function will do is load the name of the current
1650+ working directory, if it isn't already present. This could
1651+ occur if the user switched to the dotdot entry of a
1652+ subdirectory immediately before calling this function. The
1653+ function will then copy the current working directory name
1654+ into the buffer backwards, and insert a backslash character.
1655+ Next, the function will continuously switch to the previous
1656+ directories and copy their names backwards into the buffer
1657+ until it reaches the root. If the buffer overflows, it
1658+ will be treated as a circular buffer, and data will be
1659+ copied over existing characters, starting at the beginning.
1660+ Once the root directory is reached, the text in the buffer
1661+ will be swapped, so that the buffer contains as much of the
1662+ current working directory name as possible, starting at the
1663+ root.
1664+ Remarks:
1665+ None
1666+ **************************************************************/
1667+
1668+char * FSgetcwd (char * path, int numbchars);
1669+
1670+#ifdef SUPPORT_LFN
1671+/**************************************************************
1672+ Function:
1673+ char * wFSgetcwd (unsigned short int * path, int numchars)
1674+ Summary:
1675+ Get the current working directory path in UTF16 format
1676+ Conditions:
1677+ None
1678+ Input:
1679+ path - Pointer to the array to return the cwd name in
1680+ numchars - Number of chars in the path
1681+ Return Values:
1682+ char * - The cwd name string pointer (path or defaultArray)
1683+ NULL - The current working directory name could not be loaded.
1684+ Side Effects:
1685+ The FSerrno variable will be changed
1686+ Description:
1687+ The FSgetcwd function will get the name of the current
1688+ working directory and return it to the user. The name
1689+ will be copied into the buffer pointed to by 'path,'
1690+ starting at the root directory and copying as many chars
1691+ as possible before the end of the buffer. The buffer
1692+ size is indicated by the 'numchars' argument. The first
1693+ thing this function will do is load the name of the current
1694+ working directory, if it isn't already present. This could
1695+ occur if the user switched to the dotdot entry of a
1696+ subdirectory immediately before calling this function. The
1697+ function will then copy the current working directory name
1698+ into the buffer backwards, and insert a backslash character.
1699+ Next, the function will continuously switch to the previous
1700+ directories and copy their names backwards into the buffer
1701+ until it reaches the root. If the buffer overflows, it
1702+ will be treated as a circular buffer, and data will be
1703+ copied over existing characters, starting at the beginning.
1704+ Once the root directory is reached, the text in the buffer
1705+ will be swapped, so that the buffer contains as much of the
1706+ current working directory name as possible, starting at the
1707+ root.
1708+ Remarks:
1709+ None
1710+ **************************************************************/
1711+
1712+char * wFSgetcwd (unsigned short int * path, int numbchars);
1713+#endif
1714+
1715+#ifdef ALLOW_WRITES
1716+
1717+/**************************************************************************
1718+ Function:
1719+ int FSmkdir (char * path)
1720+ Summary:
1721+ Create a directory as per the Ascii input path
1722+ Conditions:
1723+ None
1724+ Input:
1725+ path - The path of directories to create.
1726+ Return Values:
1727+ 0 - The specified directory was created successfully
1728+ EOF - The specified directory could not be created
1729+ Side Effects:
1730+ Will create all non-existent directories in the path. The FSerrno
1731+ variable will be changed.
1732+ Description:
1733+ The FSmkdir function passes a RAM pointer to the path to the
1734+ mkdirhelper function.
1735+ Remarks:
1736+ None
1737+ **************************************************************************/
1738+
1739+int FSmkdir (char * path);
1740+
1741+#ifdef SUPPORT_LFN
1742+/**************************************************************************
1743+ Function:
1744+ int wFSmkdir (unsigned short int * path)
1745+ Summary:
1746+ Create a directory as per the UTF16 input path
1747+ Conditions:
1748+ None
1749+ Input:
1750+ path - The path of directories to create.
1751+ Return Values:
1752+ 0 - The specified directory was created successfully
1753+ EOF - The specified directory could not be created
1754+ Side Effects:
1755+ Will create all non-existent directories in the path. The FSerrno
1756+ variable will be changed.
1757+ Description:
1758+ The wFSmkdir function passes a RAM pointer to the path to the
1759+ mkdirhelper function.
1760+ Remarks:
1761+ None
1762+ **************************************************************************/
1763+
1764+int wFSmkdir (unsigned short int * path);
1765+#endif
1766+
1767+/**************************************************************************
1768+ Function:
1769+ int FSrmdir (char * path)
1770+ Summary:
1771+ Delete a directory as per the Ascii input path
1772+ Conditions:
1773+ None
1774+ Input:
1775+ path - The path of the directory to remove
1776+ rmsubdirs -
1777+ - TRUE - All sub-dirs and files in the target dir will be removed
1778+ - FALSE - FSrmdir will not remove non-empty directories
1779+ Return Values:
1780+ 0 - The specified directory was deleted successfully
1781+ EOF - The specified directory could not be deleted
1782+ Side Effects:
1783+ The FSerrno variable will be changed.
1784+ Description:
1785+ The FSrmdir function passes a RAM pointer to the path to the
1786+ rmdirhelper function.
1787+ Remarks:
1788+ None.
1789+ **************************************************************************/
1790+
1791+int FSrmdir (char * path, unsigned char rmsubdirs);
1792+
1793+#ifdef SUPPORT_LFN
1794+/**************************************************************************
1795+ Function:
1796+ int wFSrmdir (unsigned short int * path, unsigned char rmsubdirs)
1797+ Summary:
1798+ Delete a directory as per the UTF16 input path
1799+ Conditions:
1800+ None
1801+ Input:
1802+ path - The path of the directory to remove
1803+ rmsubdirs -
1804+ - TRUE - All sub-dirs and files in the target dir will be removed
1805+ - FALSE - FSrmdir will not remove non-empty directories
1806+ Return Values:
1807+ 0 - The specified directory was deleted successfully
1808+ EOF - The specified directory could not be deleted
1809+ Side Effects:
1810+ The FSerrno variable will be changed.
1811+ Description:
1812+ The wFSrmdir function passes a RAM pointer to the path to the
1813+ rmdirhelper function.
1814+ Remarks:
1815+ None.
1816+ **************************************************************************/
1817+
1818+int wFSrmdir (unsigned short int * path, unsigned char rmsubdirs);
1819+#endif
1820+
1821+#endif
1822+
1823+#endif
1824+
1825+#ifdef USERDEFINEDCLOCK
1826+
1827+
1828+/***********************************************************************************************************
1829+ Function:
1830+ int SetClockVars (unsigned int year, unsigned char month, unsigned char day, unsigned char hour, unsigned char minute, unsigned char second)
1831+ Summary:
1832+ Manually set timestamp variables
1833+ Conditions:
1834+ USERDEFINEDCLOCK macro defined in FSconfig.h.
1835+ Input:
1836+ year - The year (1980\-2107)
1837+ month - The month (1\-12)
1838+ day - The day of the month (1\-31)
1839+ hour - The hour (0\-23)
1840+ minute - The minute (0\-59)
1841+ second - The second (0\-59)
1842+ Return Values:
1843+ None
1844+ Side Effects:
1845+ Modifies global timing variables
1846+ Description:
1847+ Lets the user manually set the timing variables. The values passed in will be converted to the format
1848+ used by the FAT timestamps.
1849+ Remarks:
1850+ Call this before creating a file or directory (set create time) and
1851+ before closing a file (set last access time, last modified time)
1852+ ***********************************************************************************************************/
1853+
1854+int SetClockVars (unsigned int year, unsigned char month, unsigned char day, unsigned char hour, unsigned char minute, unsigned char second);
1855+#endif
1856+
1857+
1858+#ifdef ALLOW_FILESEARCH
1859+
1860+/***********************************************************************************
1861+ Function:
1862+ int FindFirst (const char * fileName, unsigned int attr, SearchRec * rec)
1863+ Summary:
1864+ Initial search function for the input Ascii fileName
1865+ Conditions:
1866+ None
1867+ Input:
1868+ fileName - The name to search for
1869+ - Parital string search characters
1870+ - * - Indicates the rest of the filename or extension can vary (e.g. FILE.*)
1871+ - ? - Indicates that one character in a filename can vary (e.g. F?LE.T?T)
1872+ attr - The attributes that a found file may have
1873+ - ATTR_READ_ONLY - File may be read only
1874+ - ATTR_HIDDEN - File may be a hidden file
1875+ - ATTR_SYSTEM - File may be a system file
1876+ - ATTR_VOLUME - Entry may be a volume label
1877+ - ATTR_DIRECTORY - File may be a directory
1878+ - ATTR_ARCHIVE - File may have archive attribute
1879+ - ATTR_MASK - All attributes
1880+ rec - pointer to a structure to put the file information in
1881+ Return Values:
1882+ 0 - File was found
1883+ -1 - No file matching the specified criteria was found
1884+ Side Effects:
1885+ Search criteria from previous FindFirst call on passed SearchRec object
1886+ will be lost. "utf16LFNfound" is overwritten after subsequent FindFirst/FindNext
1887+ operations.It is the responsibility of the application to read the "utf16LFNfound"
1888+ before it is lost.The FSerrno variable will be changed.
1889+ Description:
1890+ The FindFirst function will search for a file based on parameters passed in
1891+ by the user. This function will use the FILEfind function to parse through
1892+ the current working directory searching for entries that match the specified
1893+ parameters. If a file is found, its parameters are copied into the SearchRec
1894+ structure, as are the initial parameters passed in by the user and the position
1895+ of the file entry in the current working directory.If the return value of the
1896+ function is 0 then "utf16LFNfoundLength" indicates whether the file found was
1897+ long file name or short file name(8P3 format). The "utf16LFNfoundLength" is non-zero
1898+ for long file name and is zero for 8P3 format."utf16LFNfound" points to the
1899+ address of long file name if found during the operation.
1900+ Remarks:
1901+ Call FindFirst or FindFirstpgm before calling FindNext
1902+ ***********************************************************************************/
1903+
1904+int FindFirst (const char * fileName, unsigned int attr, SearchRec * rec);
1905+
1906+#ifdef SUPPORT_LFN
1907+/***********************************************************************************
1908+ Function:
1909+ int wFindFirst (const unsigned short int * fileName, unsigned int attr, SearchRec * rec)
1910+ Summary:
1911+ Initial search function for the input UTF16 fileName
1912+ Conditions:
1913+ None
1914+ Input:
1915+ fileName - The name to search for
1916+ - Parital string search characters
1917+ - * - Indicates the rest of the filename or extension can vary (e.g. FILE.*)
1918+ - ? - Indicates that one character in a filename can vary (e.g. F?LE.T?T)
1919+ attr - The attributes that a found file may have
1920+ - ATTR_READ_ONLY - File may be read only
1921+ - ATTR_HIDDEN - File may be a hidden file
1922+ - ATTR_SYSTEM - File may be a system file
1923+ - ATTR_VOLUME - Entry may be a volume label
1924+ - ATTR_DIRECTORY - File may be a directory
1925+ - ATTR_ARCHIVE - File may have archive attribute
1926+ - ATTR_MASK - All attributes
1927+ rec - pointer to a structure to put the file information in
1928+ Return Values:
1929+ 0 - File was found
1930+ -1 - No file matching the specified criteria was found
1931+ Side Effects:
1932+ Search criteria from previous wFindFirst call on passed SearchRec object
1933+ will be lost. "utf16LFNfound" is overwritten after subsequent wFindFirst/FindNext
1934+ operations.It is the responsibility of the application to read the "utf16LFNfound"
1935+ before it is lost.The FSerrno variable will be changed.
1936+ Description:
1937+ The wFindFirst function will search for a file based on parameters passed in
1938+ by the user. This function will use the FILEfind function to parse through
1939+ the current working directory searching for entries that match the specified
1940+ parameters. If a file is found, its parameters are copied into the SearchRec
1941+ structure, as are the initial parameters passed in by the user and the position
1942+ of the file entry in the current working directory.If the return value of the
1943+ function is 0 then "utf16LFNfoundLength" indicates whether the file found was
1944+ long file name or short file name(8P3 format). The "utf16LFNfoundLength" is non-zero
1945+ for long file name and is zero for 8P3 format."utf16LFNfound" points to the
1946+ address of long file name if found during the operation.
1947+ Remarks:
1948+ Call FindFirst or FindFirstpgm before calling FindNext
1949+ ***********************************************************************************/
1950+
1951+int wFindFirst (const unsigned short int * fileName, unsigned int attr, SearchRec * rec);
1952+#endif
1953+
1954+/**********************************************************************
1955+ Function:
1956+ int FindNext (SearchRec * rec)
1957+ Summary:
1958+ Sequential search function
1959+ Conditions:
1960+ None
1961+ Input:
1962+ rec - The structure to store the file information in
1963+ Return Values:
1964+ 0 - File was found
1965+ -1 - No additional files matching the specified criteria were found
1966+ Side Effects:
1967+ Search criteria from previous FindNext call on passed SearchRec object
1968+ will be lost. "utf16LFNfound" is overwritten after subsequent FindFirst/FindNext
1969+ operations.It is the responsibility of the application to read the "utf16LFNfound"
1970+ before it is lost.The FSerrno variable will be changed.
1971+ Description:
1972+ The FindNext function performs the same function as the FindFirst
1973+ funciton, except it does not copy any search parameters into the
1974+ SearchRec structure (only info about found files) and it begins
1975+ searching at the last directory entry offset at which a file was
1976+ found, rather than at the beginning of the current working
1977+ directory.If the return value of the function is 0 then "utf16LFNfoundLength"
1978+ indicates whether the file found was long file name or short file
1979+ name(8P3 format). The "utf16LFNfoundLength" is non-zero for long file name
1980+ and is zero for 8P3 format."utf16LFNfound" points to the address of long
1981+ file name if found during the operation.
1982+ Remarks:
1983+ Call FindFirst or FindFirstpgm before calling this function
1984+ **********************************************************************/
1985+
1986+int FindNext (SearchRec * rec);
1987+#endif
1988+
1989+
1990+/**********************************************************************
1991+ Function:
1992+ // PIC24/30/33/32
1993+ int FSfprintf (FSFILE * fptr, const char * fmt, ...)
1994+ // PIC18
1995+ int FSfpritnf (FSFILE * fptr, const rom char * fmt, ...)
1996+ Summary:
1997+ Function to write formatted strings to a file
1998+ Conditions:
1999+ For PIC18, integer promotion must be enabled in the project build
2000+ options menu. File opened in a write mode.
2001+ Input:
2002+ fptr - A pointer to the file to write to.
2003+ fmt - A string of characters and format specifiers to write to
2004+ the file
2005+ ... - Additional arguments inserted in the string by format
2006+ specifiers
2007+ Returns:
2008+ The number of characters written to the file
2009+ Side Effects:
2010+ The FSerrno variable will be changed.
2011+ Description:
2012+ Writes a specially formatted string to a file.
2013+ Remarks:
2014+ Consult AN1045 for a full description of how to use format
2015+ specifiers.
2016+ **********************************************************************/
2017+
2018+#ifdef ALLOW_FSFPRINTF
2019+ #ifdef __18CXX
2020+ int FSfprintf (FSFILE *fptr, const rom char *fmt, ...);
2021+ #else
2022+ int FSfprintf (FSFILE *fptr, const char * fmt, ...);
2023+ #endif
2024+#endif
2025+
2026+
2027+/**************************************************************************
2028+ Function:
2029+ int FSerror (void)
2030+ Summary:
2031+ Return an error code for the last function call
2032+ Conditions:
2033+ The return value depends on the last function called.
2034+ Input:
2035+ None
2036+ Side Effects:
2037+ None.
2038+ Return Values:
2039+ FSInit -
2040+ - CE_GOOD ・ No Error
2041+ - CE_INIT_ERROR ・ The physical media could not be initialized
2042+ - CE_BAD_SECTOR_READ ・ The MBR or the boot sector could not be
2043+ read correctly
2044+ - CE_BAD_PARITION ・ The MBR signature code was incorrect.
2045+ - CE_NOT_FORMATTED ・ The boot sector signature code was incorrect or
2046+ indicates an invalid number of bytes per sector.
2047+ - CE_CARDFAT32 ・ The physical media is FAT32 type (only an error
2048+ when FAT32 support is disabled).
2049+ - CE_UNSUPPORTED_FS ・ The device is formatted with an unsupported file
2050+ system (not FAT12 or 16).
2051+ FSfopen -
2052+ - CE_GOOD ・ No Error
2053+ - CE_NOT_INIT ・ The device has not been initialized.
2054+ - CE_TOO_MANY_FILES_OPEN ・ The function could not allocate any
2055+ additional file information to the array
2056+ of FSFILE structures or the heap.
2057+ - CE_INVALID_FILENAME ・ The file name argument was invalid.
2058+ - CE_INVALID_ARGUMENT ・ The user attempted to open a directory in a
2059+ write mode or specified an invalid mode argument.
2060+ - CE_FILE_NOT_FOUND ・ The specified file (which was to be opened in read
2061+ mode) does not exist on the device.
2062+ - CE_BADCACHEREAD ・ A read from the device failed.
2063+ - CE_ERASE_FAIL ・ The existing file could not be erased (when opening
2064+ a file in WRITE mode).
2065+ - CE_DIR_FULL ・ The directory is full.
2066+ - CE_DISK_FULL・ The data memory section is full.
2067+ - CE_WRITE_ERROR ・ A write to the device failed.
2068+ - CE_SEEK_ERROR ・ The current position in the file could not be set to
2069+ the end (when the file was opened in APPEND mode).
2070+ FSfclose -
2071+ - CE_GOOD ・ No Error
2072+ - CE_WRITE_ERROR ・ The existing data in the data buffer or the new file
2073+ entry information could not be written to the device.
2074+ - CE_BADCACHEREAD ・ The file entry information could not be cached
2075+ FSfread -
2076+ - CE_GOOD ・ No Error
2077+ - CE_WRITEONLY ・ The file was opened in a write-only mode.
2078+ - CE_WRITE_ERROR ・ The existing data in the data buffer could not be
2079+ written to the device.
2080+ - CE_BAD_SECTOR_READ ・ The data sector could not be read.
2081+ - CE_EOF ・ The end of the file was reached.
2082+ - CE_COULD_NOT_GET_CLUSTER ・Additional clusters in the file could not be loaded.
2083+ FSfwrite -
2084+ - CE_GOOD ・ No Error
2085+ - CE_READONLY ・ The file was opened in a read-only mode.
2086+ - CE_WRITE_PROTECTED ・ The device write-protect check function indicated
2087+ that the device has been write-protected.
2088+ - CE_WRITE_ERROR ・ There was an error writing data to the device.
2089+ - CE_BADCACHEREAD ・ The data sector to be modified could not be read from
2090+ the device.
2091+ - CE_DISK_FULL ・ All data clusters on the device are in use.
2092+ FSfseek -
2093+ - CE_GOOD ・ No Error
2094+ - CE_WRITE_ERROR ・ The existing data in the data buffer could not be
2095+ written to the device.
2096+ - CE_INVALID_ARGUMENT ・ The specified offset exceeds the size of the file.
2097+ - CE_BADCACHEREAD ・ The sector that contains the new current position
2098+ could not be loaded.
2099+ - CE_COULD_NOT_GET_CLUSTER ・Additional clusters in the file could not be
2100+ loaded/allocated.
2101+ FSftell -
2102+ - CE_GOOD ・ No Error
2103+ FSattrib -
2104+ - CE_GOOD ・ No Error
2105+ - CE_INVALID_ARGUMENT ・ The attribute argument was invalid.
2106+ - CE_BADCACHEREAD ・ The existing file entry information could not be
2107+ loaded.
2108+ - CE_WRITE_ERROR ・ The file entry information could not be written to
2109+ the device.
2110+ FSrename -
2111+ - CE_GOOD ・ No Error
2112+ - CE_FILENOTOPENED ・ A null file pointer was passed into the function.
2113+ - CE_INVALID_FILENAME ・ The file name passed into the function was invalid.
2114+ - CE_BADCACHEREAD ・ A read from the device failed.
2115+ - CE_FILENAME_EXISTS ・ A file with the specified name already exists.
2116+ - CE_WRITE_ERROR ・ The new file entry data could not be written to the
2117+ device.
2118+ FSfeof -
2119+ - CE_GOOD ・ No Error
2120+ FSformat -
2121+ - CE_GOOD ・ No Error
2122+ - CE_INIT_ERROR ・ The device could not be initialized.
2123+ - CE_BADCACHEREAD ・ The master boot record or boot sector could not be
2124+ loaded successfully.
2125+ - CE_INVALID_ARGUMENT ・ The user selected to create their own boot sector on
2126+ a device that has no master boot record, or the mode
2127+ argument was invalid.
2128+ - CE_WRITE_ERROR ・ The updated MBR/Boot sector could not be written to
2129+ the device.
2130+ - CE_BAD_PARTITION ・ The calculated number of sectors per clusters was
2131+ invalid.
2132+ - CE_NONSUPPORTED_SIZE ・ The card has too many sectors to be formatted as
2133+ FAT12 or FAT16.
2134+ FSremove -
2135+ - CE_GOOD ・ No Error
2136+ - CE_WRITE_PROTECTED ・ The device write-protect check function indicated
2137+ that the device has been write-protected.
2138+ - CE_INVALID_FILENAME ・ The specified filename was invalid.
2139+ - CE_FILE_NOT_FOUND ・ The specified file could not be found.
2140+ - CE_ERASE_FAIL ・ The file could not be erased.
2141+ FSchdir -
2142+ - CE_GOOD ・ No Error
2143+ - CE_INVALID_ARGUMENT ・ The path string was mis-formed or the user tried to
2144+ change to a non-directory file.
2145+ - CE_BADCACHEREAD ・ A directory entry could not be cached.
2146+ - CE_DIR_NOT_FOUND ・ Could not find a directory in the path.
2147+ FSgetcwd -
2148+ - CE_GOOD ・ No Error
2149+ - CE_INVALID_ARGUMENT ・ The user passed a 0-length buffer into the function.
2150+ - CE_BADCACHEREAD ・ A directory entry could not be cached.
2151+ - CE_BAD_SECTOR_READ ・ The function could not determine a previous directory
2152+ of the current working directory.
2153+ FSmkdir -
2154+ - CE_GOOD ・ No Error
2155+ - CE_WRITE_PROTECTED ・ The device write-protect check function indicated
2156+ that the device has been write-protected.
2157+ - CE_INVALID_ARGUMENT ・ The path string was mis-formed.
2158+ - CE_BADCACHEREAD ・ Could not successfully change to a recently created
2159+ directory to store its dir entry information, or
2160+ could not cache directory entry information.
2161+ - CE_INVALID_FILENAME ・ One or more of the directory names has an invalid
2162+ format.
2163+ - CE_WRITE_ERROR ・ The existing data in the data buffer could not be
2164+ written to the device or the dot/dotdot entries could
2165+ not be written to a newly created directory.
2166+ - CE_DIR_FULL ・ There are no available dir entries in the CWD.
2167+ - CE_DISK_FULL ・ There are no available clusters in the data region of
2168+ the device.
2169+ FSrmdir -
2170+ - CE_GOOD ・ No Error
2171+ - CE_DIR_NOT_FOUND ・ The directory specified could not be found or the
2172+ function could not change to a subdirectory within
2173+ the directory to be deleted (when recursive delete is
2174+ enabled).
2175+ - CE_INVALID_ARGUMENT ・ The user tried to remove the CWD or root directory.
2176+ - CE_BADCACHEREAD ・ A directory entry could not be cached.
2177+ - CE_DIR_NOT_EMPTY ・ The directory to be deleted was not empty and
2178+ recursive subdirectory removal was disabled.
2179+ - CE_ERASE_FAIL ・ The directory or one of the directories or files
2180+ within it could not be deleted.
2181+ - CE_BAD_SECTOR_READ ・ The function could not determine a previous directory
2182+ of the CWD.
2183+ SetClockVars -
2184+ - CE_GOOD ・ No Error
2185+ - CE_INVALID_ARGUMENT ・ The time values passed into the function were
2186+ invalid.
2187+ FindFirst -
2188+ - CE_GOOD ・ No Error
2189+ - CE_INVALID_FILENAME ・ The specified filename was invalid.
2190+ - CE_FILE_NOT_FOUND ・ No file matching the specified criteria was found.
2191+ - CE_BADCACHEREAD ・ The file information for the file that was found
2192+ could not be cached.
2193+ FindNext -
2194+ - CE_GOOD ・ No Error
2195+ - CE_NOT_INIT ・ The SearchRec object was not initialized by a call to
2196+ FindFirst.
2197+ - CE_INVALID_ARGUMENT ・ The SearchRec object was initialized in a different
2198+ directory from the CWD.
2199+ - CE_INVALID_FILENAME ・ The filename is invalid.
2200+ - CE_FILE_NOT_FOUND ・ No file matching the specified criteria was found.
2201+ FSfprintf -
2202+ - CE_GOOD ・ No Error
2203+ - CE_WRITE_ERROR ・ Characters could not be written to the file.
2204+ Description:
2205+ The FSerror function will return the FSerrno variable. This global
2206+ variable will have been set to an error value during the last call of a
2207+ library function.
2208+ Remarks:
2209+ None
2210+ **************************************************************************/
2211+
2212+int FSerror (void);
2213+
2214+
2215+/*********************************************************************************
2216+ Function:
2217+ int FSCreateMBR (unsigned long firstSector, unsigned long numSectors)
2218+ Summary:
2219+ Creates a master boot record
2220+ Conditions:
2221+ The I/O pins for the device have been initialized by the InitIO function.
2222+ Input:
2223+ firstSector - The first sector of the partition on the device (cannot
2224+ be 0; that's the MBR)
2225+ numSectors - The number of sectors available in memory (including the
2226+ MBR)
2227+ Return Values:
2228+ 0 - MBR was created successfully
2229+ EOF - MBR could not be created
2230+ Side Effects:
2231+ None
2232+ Description:
2233+ This function can be used to create a master boot record for a device. Note
2234+ that this function should not be used on a device that is already formatted
2235+ with a master boot record (i.e. most SD cards, CF cards, USB keys). This
2236+ function will fill the global data buffer with appropriate partition information
2237+ for a FAT partition with a type determined by the number of sectors available
2238+ to the partition. It will then write the MBR information to the first sector
2239+ on the device. This function should be followed by a call to FSformat, which
2240+ will create a boot sector, root dir, and FAT appropriate the the information
2241+ contained in the new master boot record. Note that FSformat only supports
2242+ FAT12 and FAT16 formatting at this time, and so cannot be used to format a
2243+ device with more than 0x3FFD5F sectors.
2244+ Remarks:
2245+ This function can damage the device being used, and should not be called
2246+ unless the user is sure about the size of the device and the first sector value.
2247+ *********************************************************************************/
2248+
2249+int FSCreateMBR (unsigned long firstSector, unsigned long numSectors);
2250+
2251+
2252+#ifdef ALLOW_GET_DISK_PROPERTIES
2253+/*********************************************************************************
2254+ Function:
2255+ void FSGetDiskProperties(FS_DISK_PROPERTIES* properties)
2256+ Summary:
2257+ Allows user to get the disk properties (size of disk, free space, etc)
2258+ Conditions:
2259+ 1) ALLOW_GET_DISK_PROPERTIES must be defined in FSconfig.h
2260+ 2) a FS_DISK_PROPERTIES object must be created before the function is called
2261+ 3) the new_request member of the FS_DISK_PROPERTIES object must be set before
2262+ calling the function for the first time. This will start a new search.
2263+ 4) this function should not be called while there is a file open. Close all
2264+ files before calling this function.
2265+ Input:
2266+ properties - a pointer to a FS_DISK_PROPERTIES object where the results should
2267+ be stored.
2268+ Return Values:
2269+ This function returns void. The properties_status of the previous call of
2270+ this function is located in the properties.status field. This field has
2271+ the following possible values:
2272+
2273+ FS_GET_PROPERTIES_NO_ERRORS - operation completed without error. Results
2274+ are in the properties object passed into the function.
2275+ FS_GET_PROPERTIES_DISK_NOT_MOUNTED - there is no mounted disk. Results in
2276+ properties object is not valid
2277+ FS_GET_PROPERTIES_CLUSTER_FAILURE - there was a failure trying to read a
2278+ cluster from the drive. The results in the properties object is a partial
2279+ result up until the point of the failure.
2280+ FS_GET_PROPERTIES_STILL_WORKING - the search for free sectors is still in
2281+ process. Continue calling this function with the same properties pointer
2282+ until either the function completes or until the partial results meets the
2283+ application needs. The properties object contains the partial results of
2284+ the search and can be used by the application.
2285+ Side Effects:
2286+ Can cause errors if called when files are open. Close all files before
2287+ calling this function.
2288+
2289+ Calling this function without setting the new_request member on the first
2290+ call can result in undefined behavior and results.
2291+
2292+ Calling this function after a result is returned other than
2293+ FS_GET_PROPERTIES_STILL_WORKING can result in undefined behavior and results.
2294+ Description:
2295+ This function returns the information about the mounted drive. The results
2296+ member of the properties object passed into the function is populated with
2297+ the information about the drive.
2298+
2299+ Before starting a new request, the new_request member of the properties
2300+ input parameter should be set to TRUE. This will initiate a new search
2301+ request.
2302+
2303+ This function will return before the search is complete with partial results.
2304+ All of the results except the free_clusters will be correct after the first
2305+ call. The free_clusters will contain the number of free clusters found up
2306+ until that point, thus the free_clusters result will continue to grow until
2307+ the entire drive is searched. If an application only needs to know that a
2308+ certain number of bytes is available and doesn't need to know the total free
2309+ size, then this function can be called until the required free size is
2310+ verified. To continue a search, pass a pointer to the same FS_DISK_PROPERTIES
2311+ object that was passed in to create the search.
2312+
2313+ A new search request sould be made once this function has returned a value
2314+ other than FS_GET_PROPERTIES_STILL_WORKING. Continuing a completed search
2315+ can result in undefined behavior or results.
2316+
2317+ Typical Usage:
2318+ <code>
2319+ FS_DISK_PROPERTIES disk_properties;
2320+
2321+ disk_properties.new_request = TRUE;
2322+
2323+ do
2324+ {
2325+ FSGetDiskProperties(&disk_properties);
2326+ } while (disk_properties.properties_status == FS_GET_PROPERTIES_STILL_WORKING);
2327+ </code>
2328+
2329+ results.disk_format - contains the format of the drive. Valid results are
2330+ FAT12(1), FAT16(2), or FAT32(3).
2331+
2332+ results.sector_size - the sector size of the mounted drive. Valid values are
2333+ 512, 1024, 2048, and 4096.
2334+
2335+ results.sectors_per_cluster - the number sectors per cluster.
2336+
2337+ results.total_clusters - the number of total clusters on the drive. This
2338+ can be used to calculate the total disk size (total_clusters *
2339+ sectors_per_cluster * sector_size = total size of drive in bytes)
2340+
2341+ results.free_clusters - the number of free (unallocated) clusters on the drive.
2342+ This can be used to calculate the total free disk size (free_clusters *
2343+ sectors_per_cluster * sector_size = total size of drive in bytes)
2344+
2345+ Remarks:
2346+ PIC24F size estimates:
2347+ Flash - 400 bytes (-Os setting)
2348+
2349+ PIC24F speed estimates:
2350+ Search takes approximately 7 seconds per Gigabyte of drive space. Speed
2351+ will vary based on the number of sectors per cluster and the sector size.
2352+ *********************************************************************************/
2353+void FSGetDiskProperties(FS_DISK_PROPERTIES* properties);
2354+#endif
2355+
2356+
2357+#endif