• R/O
  • SSH
  • HTTPS

コミット

タグ
未設定

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

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

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


コミットメタ情報

リビジョン270 (tree)
日時2018-08-04 05:14:27
作者kmorimatsu

ログメッセージ

Megalopa ver 1.0

変更サマリ

差分

--- mips/tags/megalopa1.0/lib_video_megalopa.h (nonexistent)
+++ mips/tags/megalopa1.0/lib_video_megalopa.h (revision 270)
@@ -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/tags/megalopa1.0/help.txt (nonexistent)
+++ mips/tags/megalopa1.0/help.txt (revision 270)
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
--- mips/tags/megalopa1.0/main.c (nonexistent)
+++ mips/tags/megalopa1.0/main.c (revision 270)
@@ -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/tags/megalopa1.0/io.c (nonexistent)
+++ mips/tags/megalopa1.0/io.c (revision 270)
@@ -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/tags/megalopa1.0/main.h (nonexistent)
+++ mips/tags/megalopa1.0/main.h (revision 270)
@@ -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/tags/megalopa1.0/music.c (nonexistent)
+++ mips/tags/megalopa1.0/music.c (revision 270)
@@ -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/tags/megalopa1.0/envspecific.c (nonexistent)
+++ mips/tags/megalopa1.0/envspecific.c (revision 270)
@@ -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/tags/megalopa1.0/compiler.h (nonexistent)
+++ mips/tags/megalopa1.0/compiler.h (revision 270)
@@ -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/tags/megalopa1.0/function.c (nonexistent)
+++ mips/tags/megalopa1.0/function.c (revision 270)
@@ -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/tags/megalopa1.0/library.c (nonexistent)
+++ mips/tags/megalopa1.0/library.c (revision 270)
@@ -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/tags/megalopa1.0/statement.c (nonexistent)
+++ mips/tags/megalopa1.0/statement.c (revision 270)
@@ -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/tags/megalopa1.0/error.c (nonexistent)
+++ mips/tags/megalopa1.0/error.c (revision 270)
@@ -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/tags/megalopa1.0/debug.h (nonexistent)
+++ mips/tags/megalopa1.0/debug.h (revision 270)
@@ -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/tags/megalopa1.0/editor.c (nonexistent)
+++ mips/tags/megalopa1.0/editor.c (revision 270)
@@ -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);