• R/O
  • SSH
  • HTTPS

コミット

タグ
未設定

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

javaandroidc++objective-ccocoa誰得c#gamebathyscaphelinuxphpqt翻訳rubypythoncwindowsomegattwitterguiframeworkbtronvb.netdirectxtestdomarduino計画中(planning stage)previewerpukiwiki

BASIC compiler/interpreter for PIC32MX/MZ-80K


コミットメタ情報

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

ログメッセージ

Megalopa ver 1.0

変更サマリ

差分

--- mips/tags/megalopa1.0/compiler.h (revision 0)
+++ 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/file.c (revision 0)
+++ mips/tags/megalopa1.0/file.c (revision 270)
@@ -0,0 +1,99 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by K.Tanaka & Katsumi
4+ http://www.ze.em-net.ne.jp/~kenken/index.html
5+ http://hp.vector.co.jp/authors/VA016157/
6+*/
7+
8+#include <xc.h>
9+#include "api.h"
10+#include "compiler.h"
11+
12+static FSFILE* g_fhandle;
13+static char* g_fbuff;
14+static int g_size;
15+
16+char* init_file(char* buff,char* appname){
17+ // Open file
18+ g_fhandle=FSfopen(appname,"r");
19+ if (!g_fhandle) {
20+ return ERR_UNKNOWN;
21+ }
22+ g_fbuff=buff;
23+ g_line=0;
24+ g_fileline=0;
25+ return 0;
26+}
27+
28+void close_file(){
29+ FSfclose(g_fhandle);
30+}
31+
32+void read_file(int blocklen){
33+ int i;
34+ static char in_string, escape;
35+ // blocklen is either 512 or 256.
36+ if (blocklen==512) {
37+ // This is first read. Initialize parameter(s).
38+ in_string=0;
39+ escape=0;
40+ } else if (g_size<512) {
41+ // Already reached the end of file.
42+ return;
43+ } else {
44+ // Shift buffer and source position 256 bytes.
45+ for(i=0;i<256;i++) g_fbuff[i]=g_fbuff[i+256];
46+ g_srcpos-=256;
47+ }
48+ // Read 512 or 256 bytes from SD card.
49+ g_size=512-blocklen+FSfread((void*)&g_fbuff[512-blocklen],1,blocklen,g_fhandle);
50+ // Some modifications of text for easy compiling.
51+ for(i=512-blocklen;i<512;i++){
52+ if (in_string) {
53+ if (g_fbuff[i]=='\\' && !escape) {
54+ escape=1;
55+ } else {
56+ escape=0;
57+ if (g_fbuff[i]=='"') in_string=0;
58+ }
59+ } else {
60+ // If not in string, all upper cases.
61+ if (g_fbuff[i]=='"') in_string=1;
62+ else if ('a'<=g_fbuff[i] && g_fbuff[i]<='z') g_fbuff[i]+='A'-'a';
63+ // If not in string, tabs will be spaces.
64+ else if ('\t'==g_fbuff[i]) g_fbuff[i]=' ';
65+ }
66+ if (g_fbuff[i]==0x0a || g_fbuff[i]==0x0d) in_string=escape=0;
67+ }
68+ return;
69+}
70+
71+char* compile_file(){
72+ int i;
73+ char* err;
74+ // Read first 512 bytes
75+ read_file(512);
76+ // Compile line by line
77+ while (g_size==512) {
78+ err=compile_line();
79+ if (err) return err;
80+ // Maintain at least 256 characters in cache.
81+ if (256<=g_srcpos) read_file(256);
82+ }
83+ // Return code at the end
84+ g_source[g_size]=0x0d;
85+ // Compile last few lines.
86+ while(g_srcpos<g_size-1){
87+ err=compile_line();
88+ if (err) return err;
89+ }
90+ // Add "DATA 0" and "END" statements.
91+ g_source="DATA 0:END\n";
92+ g_srcpos=0;
93+ err=compile_line();
94+ if (err) return err;
95+ g_srcpos=-1;
96+ // No error occured
97+ return 0;
98+}
99+
--- mips/tags/megalopa1.0/main.c (revision 0)
+++ 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/linker.c (revision 0)
+++ mips/tags/megalopa1.0/linker.c (revision 270)
@@ -0,0 +1,390 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by Katsumi.
4+ http://hp.vector.co.jp/authors/VA016157/
5+ kmorimatsu@users.sourceforge.jp
6+*/
7+
8+#include "compiler.h"
9+
10+unsigned int g_label;
11+
12+char* get_label(void){
13+ unsigned int i;
14+ char b1;
15+ int prevpos;
16+ next_position();
17+ prevpos=g_srcpos;
18+ i=0;
19+ b1=g_source[g_srcpos];
20+ if ('0'<= b1 && b1<='9') {
21+ // May be line number
22+ do {
23+ i*=10;
24+ i+=b1-'0';
25+ g_srcpos++;
26+ b1=g_source[g_srcpos];
27+ } while ('0'<= b1 && b1<='9');
28+ // Check if end of the statement.
29+ if (i==0 || 65535<i) {
30+ // Line number 0 or more than 65535 is not available
31+ g_srcpos=prevpos;
32+ return ERR_SYNTAX;
33+ } else if (get_operator()) {
34+ // Oparator not found.
35+ g_label=i;
36+ return 0;
37+ } else {
38+ // This is not constant line number.
39+ g_srcpos=prevpos;
40+ g_label=0;
41+ return 0;
42+ }
43+ } else if ('A'<=b1 && b1<='Z') {
44+ // May be label
45+ do {
46+ // First character must be A-Z
47+ // From second, A-Z and 0-9 can be used.
48+ i*=36;
49+ if ('0'<=b1 && b1<='9') {
50+ i+=b1-'0';
51+ } else if (g_srcpos==prevpos) {
52+ // First character must be A-Z.
53+ // Subtract 9, resulting 1-26 but not 10-35.
54+ // This subtraction is required to maintain
55+ // final number being <0x80000000.
56+ i+=b1-'A'+1;
57+ } else {
58+ i+=b1-'A'+10;
59+ }
60+ g_srcpos++;
61+ b1=g_source[g_srcpos];
62+ } while ('0'<= b1 && b1<='9' || 'A'<=b1 && b1<='Z');
63+ // Length of the label must be between 2 and 6.
64+ if (g_srcpos-prevpos<2 || 6<g_srcpos-prevpos) {
65+ g_srcpos=prevpos;
66+ return ERR_LABEL_LONG;
67+ }
68+ // Must not be a function
69+ next_position();
70+ if (g_source[g_srcpos]=='(') {
71+ g_srcpos=prevpos;
72+ g_label=0;
73+ return 0;
74+ }
75+ g_label=i+65536;
76+ return 0;
77+ } else {
78+ g_label=0;
79+ return 0;
80+ }
81+}
82+
83+void* search_label(unsigned int label){
84+ unsigned int i,code,search1,search2;
85+ if (label&0xFFFF0000) {
86+ // Label
87+ search1=0x3C160000|((label>>16)&0x0000FFFF); //lui s6,yyyy;
88+ search2=0x36D60000|(label&0x0000FFFF); //ori s6,s6,zzzz;
89+ for(i=0;i<g_objpos;i++){
90+ code=g_object[i];
91+ if (code==search1) {
92+ if (g_object[i+1]==search2) {
93+ // Label number found
94+ return &(g_object[i]);
95+ }
96+ }
97+ if (code&0xFFFF0000==0x04110000) {
98+ // "bgezal zero," assembly found. Skip following block (strig).
99+ i+=code&0x0000FFFF;
100+ }
101+ }
102+ // Line number not found.
103+ return 0;
104+ } else {
105+ // Line number
106+ search1=0x34160000|label; //ori s6,zero,xxxx;
107+ for(i=0;i<g_objpos;i++){
108+ code=g_object[i];
109+ if (code==search1) {
110+ // Line number found
111+ return &(g_object[i]);
112+ }
113+ if (code&0xFFFF0000==0x04110000) {
114+ // "bgezal zero," assembly found. Skip following block (strig).
115+ i+=code&0x0000FFFF;
116+ }
117+ }
118+ // Line number not found.
119+ return 0;
120+ }
121+}
122+
123+void* search_breakout(unsigned int start, int* prevcode){
124+ unsigned int pos,code1,depth;
125+ // Start search from start point where BREAK statement is used.
126+ depth=0;
127+ for(pos=start;pos<g_objpos;pos++){
128+ code1=g_object[pos];
129+ switch(code1>>16){
130+ case 0x0411:
131+ // "bgezal zero," assembly found. Skip following block (strig).
132+ pos+=code1&0x0000FFFF;
133+ break;
134+ case 0x0820: // FOR
135+ case 0x0821: // WHILE
136+ case 0x0822: // DO
137+ depth++;
138+ break;
139+ case 0x0830: // NEXT
140+ case 0x0831: // WEND
141+ case 0x0832: // LOOP
142+ if (0<depth) {
143+ depth--;
144+ break;
145+ }
146+ // Destination found.
147+ // Previous code will be also set if required for CONTINUE statement.
148+ if (prevcode) prevcode[0]=g_object[pos-1];
149+ return (void*)&g_object[pos];
150+ default:
151+ break;
152+ }
153+ }
154+ return 0;
155+}
156+
157+void* search_ifout(unsigned int start){
158+ unsigned int pos,code1,depth;
159+ // Start search from start point where BREAK statement is used.
160+ depth=0;
161+ for(pos=start;pos<g_objpos;pos++){
162+ code1=g_object[pos];
163+ switch(code1>>16){
164+ case 0x0411:
165+ // "bgezal zero," assembly found. Skip following block (strig).
166+ pos+=code1&0x0000FFFF;
167+ break;
168+ case 0x3000: // Block marker
169+ if (code1==0x30008000) {
170+ // end block
171+ if (0<depth) {
172+ depth--;
173+ break;
174+ }
175+ // Destination found.
176+ return (void*)&g_object[pos];
177+ } else if (code1==0x30000000) {
178+ // begin block
179+ depth++;
180+ break;
181+ } else {
182+ break;
183+ }
184+ default:
185+ break;
186+ }
187+ }
188+ return 0;
189+}
190+
191+/*
192+ Following codes are dedicated to specific use:
193+ 0x0411xxxx: String/data block
194+ Use 0x0413xxxx (bzegall zero,xxxx) for other cases to get PC to $ra
195+ 0x0810xxxx, 0x0811xxxx: GOTO statement
196+ 0x0812xxxx, 0x0813xxxx: GOSUB statement
197+ 0x0814xxxx, 0x0815xxxx: SOUND etc, for setting v0 as pointer to DATA array.
198+ 0x0816xxxx: BREAK statemant and relatives
199+ 0x08160000: BREAK
200+ 0x08160008: CONTINUE
201+ 0x08160100: Jump to next ELSE, ELSEIF or ENDIF
202+ 0x082xyyyy: Begin block (FOR/DO/WHILE)
203+ 0x083xyyyy: End block (NEXT/LOOP/WEND)
204+ 0x00000020, 0x00000021,
205+ 0x00000022, 0x00000023: Marker for begining the DATA region.
206+ MLB 2 bits show skip byte length in DATA.
207+ 0x30000000: Begin block (IF-THEN-ELSEIF-ELSE-ENDIF)
208+ 0x30008000: End block (IF-THEN-ELSEIF-ELSE-ENDIF)
209+ 0x3000Fxxx: General purpose NOP with value 0x0000-0x0FFF.
210+
211+ IF-THEN-ELSEIF-ELSE-ENDIF is written as follows:
212+ IF-THEN: 0x30000000 0x10400000 0x30000000
213+ ELSEIF-THEN: 0x08160100 0x30008000 (conditional expression) 0x10400000 0x30000000
214+ ELSE: 0x08160100 0x30008000 0x30000000
215+ ENDIF: 0x30008000 0x30008000
216+ , where "0x10400000 0x30000000" and "0x08160100 0x30008000" will be replaced by
217+ codes jumping to next 0x30008000. The 0x30000000 - 0x30008000 blocks will be skipped.
218+*/
219+
220+char* link(void){
221+ int pos;
222+ unsigned int code1,code2,label;
223+ g_fileline=0;
224+ for(pos=0;pos<g_objpos;pos++){
225+ code1=g_object[pos];
226+ switch(code1>>16){
227+ case 0x0411:
228+ // "bgezal zero," assembly found. Skip following block (strig).
229+ pos+=code1&0x0000FFFF;
230+ break;
231+ case 0x3416:
232+ // "ori s6,zero,xxxx" found this is the first word in a line.
233+ g_fileline++;
234+ g_line=code1&0x0000FFFF;
235+ break;
236+ case 0x0810:
237+ // GOTO
238+ code2=g_object[pos+1];
239+ if ((code2&0xFFFF0000)!=0x08110000) continue;
240+ code1&=0x0000FFFF;
241+ code2&=0x0000FFFF;
242+ label=(code1<<16)|code2;
243+ code1=(int)search_label(label);
244+ g_label=label;
245+ if (!code1) return ERR_LABEL_NF;
246+ code1&=0x0FFFFFFF;
247+ code1>>=2;
248+ code1|=0x08000000; // j xxxx
249+ g_object[pos++]=code1;
250+ g_object[pos]=0x00000000; // nop
251+ break;
252+ case 0x0812:
253+ // GOSUB
254+ code2=g_object[pos+1];
255+ if ((code2&0xFFFF0000)!=0x08130000) continue;
256+ code1&=0x0000FFFF;
257+ code2&=0x0000FFFF;
258+ label=(code1<<16)|code2;
259+ code2=(int)search_label(label);
260+ g_label=label;
261+ if (!code2) return ERR_LABEL_NF;
262+ code2&=0x0FFFFFFF;
263+ code2>>=2;
264+ code2|=0x08000000; // j xxxx
265+ g_object[pos++]=0x00000000; // nop
266+ g_object[pos]=code2;
267+ break;
268+ case 0x0814:
269+ // SOUND etc, for setting v0 as pointer to label/line
270+ code2=g_object[pos+1];
271+ if ((code2&0xFFFF0000)!=0x08150000) continue;
272+ code1&=0x0000FFFF;
273+ code2&=0x0000FFFF;
274+ label=(code1<<16)|code2;
275+ code1=(int)search_label(label);
276+ g_label=label;
277+ if (!code1) return ERR_LABEL_NF;
278+ g_object[pos++]=0x3C020000|((code1>>16)&0x0000FFFF); // lui v0,xxxx
279+ g_object[pos] =0x34420000|(code1&0x0000FFFF); // ori v0,v0,xxxx
280+ break;
281+ case 0x0816:
282+ switch(code1&0xFFFF) {
283+ case 0x0000:
284+ // BREAK statement
285+ // Find next the NEXT or WHILE statement and insert jump code after this.
286+ g_label=g_line;
287+ code1=(int)search_breakout(pos,0);
288+ if (!code1) return ERR_INVALID_BREAK;
289+ code1&=0x0FFFFFFF;
290+ code1>>=2;
291+ code1|=0x08000000; // j xxxx
292+ g_object[pos]=code1;
293+ break;
294+ case 0x0008:
295+ // CONTINUE statement
296+ // Find next the NEXT or WHILE statement and insert jump code after this.
297+ g_label=g_line;
298+ code1=(int)search_breakout(pos,&g_temp);
299+ if (!code1) return ERR_INVALID_BREAK;
300+ if (0x3000F000 == (g_temp&0xFFFFF000)) {
301+ // WEND or LOOP statement found
302+ code1-=(g_temp&0x0FFF)<<2;
303+ } else {
304+ // NEXT statement found
305+ code1-=3<<2;
306+ }
307+ code1&=0x0FFFFFFF;
308+ code1>>=2;
309+ code1|=0x08000000; // j xxxx
310+ g_object[pos]=code1;
311+ break;
312+ case 0x0100:
313+ // Jump to next ENDIF
314+ g_label=g_line;
315+ // "pos+2" is for skipping next code (must be 0x30008000)
316+ code1=(int)search_ifout(pos+2);
317+ if (!code1) return ERR_INVALID_ELSEIF;
318+ code1&=0x0FFFFFFF;
319+ code1>>=2;
320+ code1|=0x08000000; // j xxxx
321+ g_object[pos]=code1;
322+ break;
323+ default:
324+ break;
325+ }
326+ break;
327+ case 0x3000:
328+ // Block marker
329+ switch(code1&0xFFFF) {
330+ case 0x0000:
331+ // Begin if block
332+ if (g_object[pos-1]==0x10400000) { // beq v0,zero,xxxx
333+ // IF-THEN or ELSEIF-THEN
334+ // Jump to next ELSE, ELSEIF or ENDIF
335+ g_label=g_line;
336+ // "pos+1" is for skipping current code (0x30000000)
337+ code1=(int)search_ifout(pos+1);
338+ if (!code1) return ERR_INVALID_ELSEIF;
339+ code1-=(int)(&g_object[pos]);
340+ code1>>=2;
341+ code1&=0x0000FFFF;
342+ code1|=0x10400000; // beq v0,zero,xxxx
343+ g_object[pos-1]=code1;
344+ break;
345+ }
346+ break;
347+ default:
348+ break;
349+ }
350+ break;
351+ case 0x0820: // FOR
352+ case 0x0830: // NEXT
353+ case 0x0821: // WHILE
354+ case 0x0831: // WEND
355+ case 0x0822: // DO
356+ case 0x0832: // WHILE
357+ // These are used for detecing the depth of structures.
358+ // Change them to stack increase/decrease commands.
359+ g_object[pos]=0x27BD0000|(code1&0x0000FFFF); //// addiu sp,sp,xx
360+ break;
361+ case 0x2407: // addiu a3,zero,xxxx
362+ if (g_object[pos-1]!=0x02E0F809) break; // jalr ra,s7
363+ // call_lib_code(x)
364+ switch(code1&0x0000FFFF){
365+ case LIB_RESTORE:
366+ // Convert label data to pointer if not dynamic
367+ code1=g_object[pos-3];
368+ code2=g_object[pos-2];
369+ if ((code1>>16)!=0x3C02) break; // lui v0,xxxx
370+ if ((code2>>16)!=0x3442) break; // ori v0,v0,xxxx
371+ label=(code1<<16)|(code2&0x0000FFFF);
372+ code1=(int)search_label(label);
373+ g_label=label;
374+ if (!code1) return ERR_LABEL_NF;
375+ code2=code1&0x0000FFFF;
376+ code1=code1>>16;
377+ g_object[pos-3]=0x3C020000|code1; // lui v0,xxxx
378+ g_object[pos-2]=0x34420000|code2; // ori v0,v0,xxxx
379+ g_object[pos]=0x24070000|LIB_RESTORE2; // addiu a3,zero,xxxx
380+ break;
381+ default:
382+ break;
383+ }
384+ break;
385+ default:
386+ break;
387+ }
388+ }
389+ return 0;
390+}
\ No newline at end of file
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
--- mips/tags/megalopa1.0/help.txt (revision 0)
+++ 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/editor.c (revision 0)
+++ 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);
2491+
2492+// TextBuffer=(_tbuf *)RAM;
2493+// clipboard=(unsigned char *)TextBuffer+sizeof(_tbuf)*TBUFMAXLINE;
2494+// filebuf=clipboard+WIDTH_XMAX*EDITWIDTHY;
2495+// cwdpath=filebuf+FILEBUFSIZE;
2496+// filenames=(unsigned char (*)[])(cwdpath+PATHNAMEMAX);
2497+// undobuf=(unsigned char *)filenames+MAXFILENUM*13;
2498+
2499+ inittextbuf(); //テキストバッファ初期化
2500+ currentfile[0]=0; //作業中ファイル名クリア
2501+ cwdpath[0]='\\'; //カレントディレクトリをルートに設定
2502+ cwdpath[1]=0;
2503+
2504+ //実行時生成一時ファイルがあった場合は読み込む
2505+ fp=FSfopen(WORKDIRFILE,"r");
2506+ if(fp!=NULL){
2507+ FSfread(cwdpath,1,PATHNAMEMAX,fp);
2508+ FSfclose(fp);
2509+ FSchdir(cwdpath);
2510+ if(loadtextfile(TEMPFILENAME)==0){
2511+ edited=1;
2512+ setcursorcolor(COLOR_ERRORTEXT);
2513+ printstr("Temporary File Loaded\n");
2514+ printstr("Current Directory is\n");
2515+ setcursorcolor(COLOR_DIR);
2516+ printstr(cwdpath);
2517+ setcursorcolor(COLOR_ERRORTEXT);
2518+ printstr("\nSave To SD Card If Necessary\n");
2519+ setcursorcolor(COLOR_NORMALTEXT);
2520+ printstr((unsigned char *)Message1); //Hit Any Key
2521+ inputchar(); //1文字入力待ち
2522+ }
2523+ else{
2524+ cwdpath[0]='\\'; //カレントディレクトリをルートに設定
2525+ cwdpath[1]=0;
2526+ }
2527+ }
2528+ cursor_top(); //カーソルをテキストバッファの先頭に移動
2529+ insertmode=1; //0:上書き、1:挿入
2530+ clipsize=0; //クリップボードクリア
2531+ blinktimer=0; //カーソル点滅タイマークリア
2532+
2533+ while(1){
2534+ redraw();//画面再描画
2535+ setcursor(cx,cy,COLOR_NORMALTEXT);
2536+ getcursorchar(); //カーソル位置の文字を退避(カーソル点滅用)
2537+ while(1){
2538+ //キー入力待ちループ
2539+ wait60thsec(1); //60分の1秒ウェイト
2540+ blinkcursorchar(); //カーソル点滅させる
2541+ k1=ps2readkey(); //キーバッファから読み込み、k1:通常文字入力の場合ASCIIコード
2542+ displaybottomline(); //画面最下行にファンクションキー機能表示
2543+ if(vkey) break; //キーが押された場合ループから抜ける
2544+ if(cursorbp1==NULL) gabagecollect1(); //1バイトガベージコレクション(範囲選択時はしない)
2545+ }
2546+ resetcursorchar(); //カーソルを元の文字表示に戻す
2547+ k2=(unsigned char)vkey; //k2:仮想キーコード
2548+ sh=vkey>>8; //sh:シフト関連キー状態
2549+ if(k2==VK_RETURN || k2==VK_SEPARATOR) k1='\n'; //Enter押下は単純に改行文字を入力とする
2550+ if(k1) normal_code_process(k1); //通常文字が入力された場合
2551+ else control_code_process(k2,sh); //制御文字が入力された場合
2552+ if(cursorbp1!=NULL && cx==cx1 && cy==cy1) cursorbp1=NULL;//選択範囲の開始と終了が重なったら範囲選択モード解除
2553+ }
2554+}
--- mips/tags/megalopa1.0/debug.c (revision 0)
+++ mips/tags/megalopa1.0/debug.c (revision 270)
@@ -0,0 +1,245 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by K.Tanaka & Katsumi
4+ http://www.ze.em-net.ne.jp/~kenken/index.html
5+ http://hp.vector.co.jp/authors/VA016157/
6+*/
7+
8+#ifdef __DEBUG
9+
10+#include <xc.h>
11+#include "api.h"
12+#include "main.h"
13+#include "compiler.h"
14+
15+/*
16+ Enable following line when debugging binary object.
17+*/
18+//#include "debugdump.h"
19+
20+
21+// Pseudo reading config setting for debug mode
22+unsigned int g_DEVCFG1=0xFF7F4DDB;
23+
24+// Construct jump assembly in boot area.
25+const unsigned int _debug_boot[] __attribute__((address(0xBFC00000))) ={
26+ 0x0B401C00,// j 0x9d007000
27+ 0x00000000,// nop
28+};
29+
30+// Use DEBUG.HEX as file name of this program.
31+const unsigned char _debug_filename[] __attribute__((address(FILENAME_FLASH_ADDRESS))) ="DEBUG.HEX";
32+
33+static const char initext[];
34+static const char bastext[];
35+
36+static char* readtext;
37+static int filepos;
38+
39+/*
40+ Debug dump
41+ In debugdump.h:
42+ __DEBUGDUMP is defined.
43+ __DEBUGDUMP_FREEAREA is defined as start address of free area (1st argument of set_free_area() function)
44+ const unsigned char dump[] is initialized.
45+*/
46+#ifdef __DEBUGDUMP
47+int debugDump(){
48+ int i;
49+ for(i=0;i<sizeof dump;i++){
50+ RAM[i]=dump[i];
51+ }
52+
53+ g_objpos=(__DEBUGDUMP_FREEAREA-(unsigned int)g_object)/4;
54+
55+ // Initialize parameters
56+ g_pcg_font=0;
57+ g_use_graphic=0;
58+ g_graphic_area=0;
59+ clearscreen();
60+ setcursor(0,0,7);
61+
62+ printstr("BASIC "BASVER"\n");
63+ wait60thsec(15);
64+
65+ printstr("Compiling...");
66+
67+ // Initialize the other parameters
68+ // Random seed
69+ g_rnd_seed=0x92D68CA2; //2463534242
70+ // Clear variables
71+ for(i=0;i<ALLOC_BLOCK_NUM;i++){
72+ g_var_mem[i]=0;
73+ g_var_size[i]=0;
74+ }
75+ // Clear key input buffer
76+ for(i=0;i<256;i++){
77+ ps2keystatus[i]=0;
78+ }
79+ // Reset data/read.
80+ reset_dataread();
81+
82+ // Assign memory
83+ set_free_area((void*)(g_object+g_objpos),(void*)(&RAM[RAMSIZE]));
84+ // Execute program
85+ // Start program from the beginning of RAM.
86+ // Work area (used for A-Z values) is next to the object code area.
87+ start_program((void*)(&(RAM[0])),(void*)(&g_var_mem[0]));
88+ printstr("\nOK\n");
89+ g_use_graphic=0;
90+
91+ return 1;
92+}
93+#else
94+int debugDump(){
95+ return 0;
96+}
97+#endif
98+
99+/*
100+ Override libsdfsio functions.
101+ Here, don't use SD card, but the vertual files
102+ (initext[] and bastext[]) are used.
103+*/
104+
105+FSFILE fsfile;
106+
107+size_t FSfread(void *ptr, size_t size, size_t n, FSFILE *stream){
108+ char b;
109+ size_t ret=0;
110+ if (!readtext) return 0;
111+ while(b=readtext[filepos]){
112+ filepos++;
113+ ((char*)ptr)[ret]=b;
114+ ret++;
115+ if (n<=ret) break;
116+ }
117+ return ret;
118+}
119+FSFILE* FSfopen(const char * fileName, const char *mode){
120+ int i;
121+ for(i=0;i<13;i++){
122+ if (fileName[i]=='.') break;
123+ }
124+ if (i==13) {
125+ // Unknown file name
126+ // Force BAS file
127+ readtext=(char*)&bastext[0];
128+ } else if (fileName[i+1]=='I' && fileName[i+2]=='N' && fileName[i+3]=='I') {
129+ // INI file
130+ readtext=(char*)&initext[0];
131+ } else if (fileName[i+1]=='B' && fileName[i+2]=='A' && fileName[i+3]=='S') {
132+ // BAS file
133+ readtext=(char*)&bastext[0];
134+ // Try debugDump.
135+ if (debugDump()) return 0;
136+ } else {
137+ readtext=0;
138+ return 0;
139+ }
140+ filepos=0;
141+ return &fsfile;
142+}
143+int FSfeof( FSFILE * stream ){
144+ return readtext[filepos]?1:0;
145+}
146+int FSfclose(FSFILE *fo){
147+ return 0;
148+}
149+int FSInit(void){
150+ return 1;
151+}
152+int FSremove (const char * fileName){
153+ return 0;
154+}
155+size_t FSfwrite(const void *ptr, size_t size, size_t n, FSFILE *stream){
156+ return 0;
157+}
158+
159+int FindFirst (const char * fileName, unsigned int attr, SearchRec * rec){
160+ return 0;
161+}
162+int FindNext (SearchRec * rec){
163+ return 0;
164+}
165+int FSmkdir (char * path){
166+ return 0;
167+}
168+char * FSgetcwd (char * path, int numchars){
169+ return 0;
170+}
171+int FSchdir (char * path){
172+ return 0;
173+}
174+long FSftell (FSFILE * fo){
175+ return 0;
176+}
177+int FSfseek(FSFILE *stream, long offset, int whence){
178+ return 0;
179+}
180+/*
181+ ps2init() is not called.
182+ Instead, not_ps2init_but_init_Timer1() is called.
183+ Timer1 is used to update drawcount and drawing gloval variables.
184+*/
185+
186+int not_ps2init_but_init_Timer1(){
187+ PR1=0x0FFF;
188+ TMR1=0;
189+ IFS0bits.T1IF=0;
190+ T1CON=0x8000;
191+ // Timer1 interrupt: priority 4
192+ IPC1bits.T1IP=4;
193+ IPC1bits.T1IS=0;
194+ IEC0bits.T1IE=1;
195+
196+ return 0;
197+}
198+
199+#pragma interrupt timer1Int IPL4SOFT vector 4
200+
201+void timer1Int(){
202+ IFS0bits.T1IF=0;
203+ if (drawing) {
204+ drawing=0;
205+ drawcount++;
206+ } else {
207+ drawing=1;
208+ }
209+}
210+
211+/*
212+ initext[] and bastext[] are vertual files
213+ as "MACHIKAN.INI" and "DEBUG.BAS".
214+*/
215+
216+
217+static const char initext[]=
218+"#PRINT\n"
219+"#PRINT\n";
220+
221+
222+static const char bastext[]=
223+"CLS\n"
224+"print NOT(0);IN(0)\n"
225+"\n";
226+
227+/*
228+ Test function for constructing assemblies from C codes.
229+*/
230+
231+int _debug_test(int a0, int a1, int a2, int a3, int param4, int param5){
232+// if (a0<0xa0008192) return 0xa0000000;
233+ asm volatile("lw $sp,18($fp)");
234+ asm volatile("addiu $sp,$sp,2044");
235+ return a2+a3;
236+}
237+
238+/*
239+ Break point used for debugging object code.
240+
241+g_object[g_objpos++]=0x0000000d;// break 0x0
242+
243+*/
244+
245+#endif // __DEBUG
--- mips/tags/megalopa1.0/main.h (revision 0)
+++ 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/error.c (revision 0)
+++ 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/editor.h (revision 0)
+++ mips/tags/megalopa1.0/editor.h (revision 270)
@@ -0,0 +1,43 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by K.Tanaka
4+ http://www.ze.em-net.ne.jp/~kenken/index.html
5+*/
6+
7+//#define TBUFMAXLINE 201 //テキストバッファ数
8+#define TBUFMAXLINE 181 //テキストバッファ数
9+
10+#define TBUFSIZE 200 //テキストバッファ1つのサイズ
11+#define TBUFMAXSIZE (TBUFSIZE*(TBUFMAXLINE-1)) //最大バッファ容量(バッファ1行分空ける)
12+//#define EDITWIDTHX 36 //エディタ画面横幅
13+#define EDITWIDTHY 26 //エディタ画面縦幅
14+#define COLOR_NORMALTEXT 7 //通常テキスト色
15+#define COLOR_ERRORTEXT 4 //エラーメッセージテキスト色
16+#define COLOR_AREASELECTTEXT 4 //範囲選択テキスト色
17+#define COLOR_BOTTOMLINE 5 //画面最下行の色
18+#define COLOR_DIR 6 //ディレクトリ名表示の色
19+#define COLOR_INV 128 //モノクロモード時の反転
20+#define FILEBUFSIZE 256 //ファイルアクセス用バッファサイズ
21+#define MAXFILENUM 200 //利用可能ファイル最大数
22+#define PATHNAMEMAX 128 //ワーキングディレクトリパス名の最大値
23+#define UNDOBUFSIZE 2048 //アンドゥ用バッファサイズ
24+
25+#define ERR_FILETOOBIG -1
26+#define ERR_CANTFILEOPEN -2
27+#define ERR_CANTWRITEFILE -3
28+
29+#define TEMPFILENAME "~TEMP.BAS" //実行時ソース保存ファイル名
30+#define WORKDIRFILE "~WORKDIR.TMP" //実行時パス保存ファイル名
31+
32+#define UNDO_INSERT 1
33+#define UNDO_OVERWRITE 2
34+#define UNDO_DELETE 3
35+#define UNDO_BACKSPACE 4
36+#define UNDO_CONTINS 5
37+#define UNDO_CONTDEL 6
38+
39+void texteditor(void); //テキストエディタ本体
40+int runbasic(char *s,int test); //コンパイルして実行
41+extern unsigned char tempfile[13];
42+void wait60thsec(unsigned short n);
43+
--- mips/tags/megalopa1.0/operator.c (revision 0)
+++ mips/tags/megalopa1.0/operator.c (revision 270)
@@ -0,0 +1,273 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by Katsumi.
4+ http://hp.vector.co.jp/authors/VA016157/
5+ kmorimatsu@users.sourceforge.jp
6+*/
7+
8+#include "compiler.h"
9+
10+/*
11+Operators: (upper ones have higher priority
12+()
13+* / %
14++ -
15+<< >>
16+< <= > >=
17+= !=
18+XOR
19+AND
20+OR
21+*/
22+
23+
24+const unsigned char g_priority[]={
25+ 0, // OP_VOID
26+ 1, // OP_OR
27+ 2, // OP_AND
28+ 3, // OP_XOR
29+ 4,4, // OP_EQ, OP_NEQ
30+ 5,5,5,5, // OP_LT, OP_LTE, OP_MT, OP_MTE
31+ 6,6, // OP_SHL, OP_SHR
32+ 7,7, // OP_ADD, OP_SUB
33+ 8,8,8 // OP_MUL, OP_DIV, OP_REM
34+};
35+
36+enum operator g_last_op;
37+
38+char* get_operator(void){
39+ char b1,b2,b3;
40+ next_position();
41+ b1=g_source[g_srcpos];
42+ b2=g_source[g_srcpos+1];
43+ b3=g_source[g_srcpos+2];
44+ switch(b1){
45+ case '%': g_last_op=OP_REM; break;
46+ case '/': g_last_op=OP_DIV; break;
47+ case '*': g_last_op=OP_MUL; break;
48+ case '-': g_last_op=OP_SUB; break;
49+ case '+': g_last_op=OP_ADD; break;
50+ case '>':
51+ if (b2=='>') {
52+ g_srcpos++;
53+ g_last_op=OP_SHR;
54+ } else if (b2=='=') {
55+ g_srcpos++;
56+ g_last_op=OP_MTE;
57+ } else {
58+ g_last_op=OP_MT;
59+ }
60+ break;
61+ case '<':
62+ if (b2=='<') {
63+ g_srcpos++;
64+ g_last_op=OP_SHL;
65+ } else if (b2=='=') {
66+ g_srcpos++;
67+ g_last_op=OP_LTE;
68+ } else {
69+ g_last_op=OP_LT;
70+ }
71+ break;
72+ case '!':
73+ if (b2!='=') return ERR_SYNTAX;
74+ g_srcpos++;
75+ g_last_op=OP_NEQ;
76+ break;
77+ case '=':
78+ if (b2=='=') g_srcpos++;
79+ g_last_op=OP_EQ;
80+ break;
81+ case 'X':
82+ if (b2!='O') return ERR_SYNTAX;
83+ if (b3!='R') return ERR_SYNTAX;
84+ g_srcpos++;
85+ g_srcpos++;
86+ g_last_op=OP_XOR;
87+ break;
88+ case 'O':
89+ if (b2!='R') return ERR_SYNTAX;
90+ g_srcpos++;
91+ g_last_op=OP_OR;
92+ break;
93+ case 'A':
94+ if (b2!='N') return ERR_SYNTAX;
95+ if (b3!='D') return ERR_SYNTAX;
96+ g_srcpos++;
97+ g_srcpos++;
98+ g_last_op=OP_AND;
99+ break;
100+ default:
101+ return ERR_SYNTAX;
102+ }
103+ g_srcpos++;
104+ return 0;
105+}
106+
107+char* get_floatOperator(void){
108+ char* err;
109+ int spos;
110+ next_position();
111+ spos=g_srcpos;
112+ err=get_operator();
113+ if (err) return err;
114+ switch(g_last_op){
115+ // Following operators cannot be used for float values.
116+ case OP_XOR:
117+ case OP_REM:
118+ case OP_SHR:
119+ case OP_SHL:
120+ g_srcpos=spos;
121+ return ERR_SYNTAX;
122+ default:
123+ return 0;
124+ }
125+}
126+
127+char* calculation(enum operator op){
128+ // $v0 = $v1 <op> $v0;
129+ switch(op){
130+ case OP_OR:
131+ check_obj_space(1);
132+ g_object[g_objpos++]=0x00621025; // or v0,v1,v0
133+ break;
134+ case OP_AND:
135+ check_obj_space(1);
136+ g_object[g_objpos++]=0x00621024; // and v0,v1,v0
137+ break;
138+ case OP_XOR:
139+ check_obj_space(1);
140+ g_object[g_objpos++]=0x00621026; // xor v0,v1,v0
141+ break;
142+ case OP_EQ:
143+ check_obj_space(2);
144+ g_object[g_objpos++]=0x00621026; // xor v0,v1,v0
145+ g_object[g_objpos++]=0x2C420001; // sltiu v0,v0,1
146+ break;
147+ case OP_NEQ:
148+ check_obj_space(2);
149+ g_object[g_objpos++]=0x00621026; // xor v0,v1,v0
150+ g_object[g_objpos++]=0x0002102B; // sltu v0,zero,v0
151+ break;
152+ case OP_LT:
153+ check_obj_space(1);
154+ g_object[g_objpos++]=0x0062102A; // slt v0,v1,v0
155+ break;
156+ case OP_LTE:
157+ check_obj_space(2);
158+ g_object[g_objpos++]=0x0043102A; // slt v0,v0,v1
159+ g_object[g_objpos++]=0x38420001; // xori v0,v0,0x1
160+ break;
161+ case OP_MT:
162+ check_obj_space(1);
163+ g_object[g_objpos++]=0x0043102A; // slt v0,v0,v1
164+ break;
165+ case OP_MTE:
166+ check_obj_space(2);
167+ g_object[g_objpos++]=0x0062102A; // slt v0,v1,v0
168+ g_object[g_objpos++]=0x38420001; // xori v0,v0,0x1
169+ break;
170+ case OP_SHR:
171+ check_obj_space(1);
172+ g_object[g_objpos++]=0x00431006; // srlv v0,v1,v0
173+ break;
174+ case OP_SHL:
175+ check_obj_space(1);
176+ g_object[g_objpos++]=0x00431004; // sllv v0,v1,v0
177+ break;
178+ case OP_ADD:
179+ check_obj_space(1);
180+ g_object[g_objpos++]=0x00621021; // addu v0,v1,v0
181+ break;
182+ case OP_SUB:
183+ check_obj_space(1);
184+ g_object[g_objpos++]=0x00621023; // subu v0,v1,v0
185+ break;
186+ case OP_MUL:
187+ check_obj_space(1);
188+ g_object[g_objpos++]=0x70621002; // mul v0,v1,v0
189+ break;
190+ case OP_DIV:
191+ // Note that intterupt functions do not use mflo and mfhi.
192+ // Probably using div does not cause delay of interrupt.
193+ check_obj_space(5);
194+ g_object[g_objpos++]=0x14400003; // bne v0,zero,label
195+ g_object[g_objpos++]=0x0062001A; // div v1,v0
196+ call_lib_code(LIB_DIV0); // 2 words
197+ // label:
198+ g_object[g_objpos++]=0x00001012; // mflo v0
199+ break;
200+ case OP_REM:
201+ check_obj_space(5);
202+ g_object[g_objpos++]=0x14400003; // bne v0,zero,label
203+ g_object[g_objpos++]=0x0062001A; // div v1,v0
204+ call_lib_code(LIB_DIV0); // 2 words
205+ // label:
206+ g_object[g_objpos++]=0x00001010; // mfhi v0
207+ break;
208+ default:
209+ return ERR_SYNTAX;
210+ }
211+ return 0;
212+}
213+
214+char* calculation_float(enum operator op){
215+ // $v0 = $a0 <op> $v0;
216+ // All the calculations will be done in library code, lib_float function (see below).
217+ call_lib_code(LIB_FLOAT | op);
218+ return 0;
219+}
220+
221+int lib_float(int ia0,int iv0, enum operator a1){
222+ // This function was called from _call_library().
223+ // Variable types must be all int.
224+ // Casting cannot be used.
225+ // Instead, by using pointer, put as int value, get as float value,
226+ // calculate, put as float value, then get as int value for returning.
227+ volatile float a0,v0;
228+ ((int*)(&a0))[0]=ia0;
229+ ((int*)(&v0))[0]=iv0;
230+ switch(a1){
231+ case OP_EQ:
232+ v0= a0==v0?1:0;
233+ break;
234+ case OP_NEQ:
235+ v0= a0!=v0?1:0;
236+ break;
237+ case OP_LT:
238+ v0= a0<v0?1:0;
239+ break;
240+ case OP_LTE:
241+ v0= a0<=v0?1:0;
242+ break;
243+ case OP_MT:
244+ v0= a0>v0?1:0;
245+ break;
246+ case OP_MTE:
247+ v0= a0>=v0?1:0;
248+ break;
249+ case OP_ADD:
250+ v0= a0+v0;
251+ break;
252+ case OP_SUB:
253+ v0= a0-v0;
254+ break;
255+ case OP_MUL:
256+ v0= a0*v0;
257+ break;
258+ case OP_DIV:
259+ if (v0==0) err_div_zero();
260+ v0= a0/v0;
261+ break;
262+ case OP_OR:
263+ v0= a0||v0?1:0;
264+ break;
265+ case OP_AND:
266+ v0= a0&&v0?1:0;
267+ break;
268+ default:
269+ err_unknown();
270+ return 0;
271+ }
272+ return ((int*)(&v0))[0];
273+};
\ No newline at end of file
--- mips/tags/megalopa1.0/debug.h (revision 0)
+++ 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/sdfsio370f.h (revision 0)
+++ mips/tags/megalopa1.0/sdfsio370f.h (revision 270)
@@ -0,0 +1,2357 @@
1+// sdfsio370f.h
2+// PIC32MX370F512HでSPI2接続されたSDカードにアクセスする
3+// sdfsio370fLib.aを利用するためのヘッダーファイル
4+// FSIO.h,FSconfig.h,FSDefs.hから抜粋 by K.Tanaka
5+//
6+// サポート
7+// FAT32,書き込み,ファイルサーチ,Dir
8+// 未サポート
9+// LongFileName,FSfprintf,format,FSGetDiskProperties
10+// 同時オープン数 3
11+
12+/******************************************************************************
13+ *
14+ * Microchip Memory Disk Drive File System
15+ *
16+ ******************************************************************************
17+ * FileName: FSIO.h
18+ * Dependencies: GenericTypeDefs.h
19+ * FSconfig.h
20+ * FSDefs.h
21+ * stddef.h
22+ * Processor: PIC18/PIC24/dsPIC30/dsPIC33/PIC32
23+ * Compiler: C18/C30/C32
24+ * Company: Microchip Technology, Inc.
25+ * Version: 1.3.0
26+ *
27+ * Software License Agreement
28+ *
29+ * The software supplied herewith by Microchip Technology Incorporated
30+ * (the 鼎ompany・ for its PICmicroョ Microcontroller is intended and
31+ * supplied to you, the Company痴 customer, for use solely and
32+ * exclusively on Microchip PICmicro Microcontroller products. The
33+ * software is owned by the Company and/or its supplier, and is
34+ * protected under applicable copyright laws. All rights are reserved.
35+ * Any use in violation of the foregoing restrictions may subject the
36+ * user to criminal sanctions under applicable laws, as well as to
37+ * civil liability for the breach of the terms and conditions of this
38+ * license.
39+ *
40+ * THIS SOFTWARE IS PROVIDED IN AN 鄭S IS・CONDITION. NO WARRANTIES,
41+ * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
42+ * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
43+ * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
44+ * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
45+ * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
46+ *
47+*****************************************************************************/
48+
49+#ifndef FS_DOT_H
50+#define FS_DOT_H
51+
52+#define MDD_MediaInitialize MDD_SDSPI_MediaInitialize
53+#define MDD_MediaDetect MDD_SDSPI_MediaDetect
54+#define MDD_SectorRead MDD_SDSPI_SectorRead
55+#define MDD_SectorWrite MDD_SDSPI_SectorWrite
56+#define MDD_InitIO MDD_SDSPI_InitIO
57+#define MDD_ShutdownMedia MDD_SDSPI_ShutdownMedia
58+#define MDD_WriteProtectState MDD_SDSPI_WriteProtectState
59+
60+#define ALLOW_FILESEARCH
61+#define ALLOW_WRITES
62+#define ALLOW_DIRS
63+#define SUPPORT_FAT32
64+
65+// Summary: An enumeration used for various error codes.
66+// Description: The CETYPE enumeration is used to indicate different error conditions during device operation.
67+typedef enum _CETYPE
68+{
69+ CE_GOOD = 0, // No error
70+ CE_ERASE_FAIL, // An erase failed
71+ CE_NOT_PRESENT, // No device was present
72+ CE_NOT_FORMATTED, // The disk is of an unsupported format
73+ CE_BAD_PARTITION, // The boot record is bad
74+ CE_UNSUPPORTED_FS, // The file system type is unsupported
75+ CE_INIT_ERROR, // An initialization error has occured
76+ CE_NOT_INIT, // An operation was performed on an uninitialized device
77+ CE_BAD_SECTOR_READ, // A bad read of a sector occured
78+ CE_WRITE_ERROR, // Could not write to a sector
79+ CE_INVALID_CLUSTER, // Invalid cluster value > maxcls
80+ CE_FILE_NOT_FOUND, // Could not find the file on the device
81+ CE_DIR_NOT_FOUND, // Could not find the directory
82+ CE_BAD_FILE, // File is corrupted
83+ CE_DONE, // No more files in this directory
84+ CE_COULD_NOT_GET_CLUSTER, // Could not load/allocate next cluster in file
85+ CE_FILENAME_2_LONG, // A specified file name is too long to use
86+ CE_FILENAME_EXISTS, // A specified filename already exists on the device
87+ CE_INVALID_FILENAME, // Invalid file name
88+ CE_DELETE_DIR, // The user tried to delete a directory with FSremove
89+ CE_DIR_FULL, // All root dir entry are taken
90+ CE_DISK_FULL, // All clusters in partition are taken
91+ CE_DIR_NOT_EMPTY, // This directory is not empty yet, remove files before deleting
92+ CE_NONSUPPORTED_SIZE, // The disk is too big to format as FAT16
93+ CE_WRITE_PROTECTED, // Card is write protected
94+ CE_FILENOTOPENED, // File not opened for the write
95+ CE_SEEK_ERROR, // File location could not be changed successfully
96+ CE_BADCACHEREAD, // Bad cache read
97+ CE_CARDFAT32, // FAT 32 - card not supported
98+ CE_READONLY, // The file is read-only
99+ CE_WRITEONLY, // The file is write-only
100+ CE_INVALID_ARGUMENT, // Invalid argument
101+ CE_TOO_MANY_FILES_OPEN, // Too many files are already open
102+ CE_UNSUPPORTED_SECTOR_SIZE // Unsupported sector size
103+} CETYPE;
104+
105+
106+// Summary: A macro indicating a dir entry was found
107+// Description: The FOUND macro indicates that a directory entry was found in the specified position
108+#define FOUND 0
109+
110+// Summary: A macro indicating no dir entry was found
111+// Description: The NOT_FOUND macro indicates that the specified directory entry to load was deleted
112+#define NOT_FOUND 1
113+
114+// Summary: A macro indicating that no more files were found
115+// Description: The NO_MORE macro indicates that there are no more directory entries to search for
116+#define NO_MORE 2
117+
118+
119+
120+// Summary: A macro indicating the device is formatted with FAT12
121+// Description: The FAT12 macro is used to indicate that the file system on the device being accessed is a FAT12 file system.
122+#define FAT12 1
123+
124+// Summary: A macro indicating the device is formatted with FAT16
125+// Description: The FAT16 macro is used to indicate that the file system on the device being accessed is a FAT16 file system.
126+#define FAT16 2
127+
128+// Summary: A macro indicating the device is formatted with FAT32
129+// Description: The FAT32 macro is used to indicate that the file system on the device being accessed is a FAT32 file system.
130+#define FAT32 3
131+
132+
133+
134+// Summary: A read-only attribute macro
135+// Description: A macro for the read-only attribute. A file with this attribute should not be written to. Note that this
136+// attribute will not actually prevent a write to the file; that functionality is operating-system dependant. The
137+// user should take care not to write to a read-only file.
138+#define ATTR_READ_ONLY 0x01
139+
140+// Summary: A hidden attribute macro
141+// Description: A macro for the hidden attribute. A file with this attribute may be hidden from the user, depending on the
142+// implementation of the operating system.
143+#define ATTR_HIDDEN 0x02
144+
145+// Summary: A system attribute macro
146+// Description: A macro for the system attribute. A file with this attribute is used by the operating system, and should not be
147+// modified. Note that this attribute will not actually prevent a write to the file.
148+#define ATTR_SYSTEM 0x04
149+
150+// Summary: A volume attribute macro
151+// Description: A macro for the volume attribute. If the first directory entry in the root directory has the volume attribute set,
152+// the device will use the name in that directory entry as the volume name.
153+#define ATTR_VOLUME 0x08
154+
155+// Summary: A macro for the attributes for a long-file name entry
156+// Description: A macro for the long-name attributes. If a directory entry is used in a long-file name implementation, it will have
157+// all four lower bits set. This indicates that any software that does not support long file names should ignore that
158+// entry.
159+#define ATTR_LONG_NAME 0x0f
160+
161+// Summary: A directory attribute macro
162+// Description: A macro for the directory attribute. If a directory entry has this attribute set, the file it points to is a directory-
163+// type file, and will contain directory entries that point to additional directories or files.
164+#define ATTR_DIRECTORY 0x10
165+
166+// Summary: An archive attribute macro
167+// Description: A macro for the archive attribute. This attribute will indicate to some archiving programs that the file with this
168+// attribute needs to be backed up. Most operating systems create files with the archive attribute set.
169+#define ATTR_ARCHIVE 0x20
170+
171+// Summary: A macro for all attributes
172+// Description: A macro for all attributes. The search functions in this library require an argument that determines which attributes
173+// a file is allowed to have in order to be found. If ATTR_MASK is specified as this argument, any file may be found, regardless
174+// of its attributes.
175+#define ATTR_MASK 0x3f
176+
177+
178+
179+// Summary: A macro to indicate an empty FAT entry
180+// Description: The CLUSTER_EMPTY value is used to indicate that a FAT entry and it's corresponding cluster are available.
181+#define CLUSTER_EMPTY 0x0000
182+
183+// Summary: A macro to indicate the last cluster value for FAT12
184+// Description: The LAST_CLUSTER_FAT12 macro is used when reading the FAT to indicate that the next FAT12 entry for a file contains
185+// the end-of-file value.
186+#define LAST_CLUSTER_FAT12 0xff8
187+
188+// Summary: A macro to indicate the last cluster value for FAT16
189+// Description: The LAST_CLUSTER_FAT16 macro is used when reading the FAT to indicate that the next FAT16 entry for a file contains
190+// the end-of-file value.
191+#define LAST_CLUSTER_FAT16 0xfff8
192+
193+// Summary: A macro to indicate the last allocatable cluster for FAT12
194+// Description: The END_CLUSTER_FAT12 value is used as a comparison in FAT12 to determine that the firmware has reached the end of
195+// the range of allowed allocatable clusters.
196+#define END_CLUSTER_FAT12 0xFF7
197+
198+// Summary: A macro to indicate the last allocatable cluster for FAT16
199+// Description: The END_CLUSTER_FAT16 value is used as a comparison in FAT16 to determine that the firmware has reached the end of
200+// the range of allowed allocatable clusters.
201+#define END_CLUSTER_FAT16 0xFFF7
202+
203+// Summary: A macro to indicate the failure of the ReadFAT function
204+// Description: The CLUSTER_FAIL_FAT16 macro is used by the ReadFAT function to indicate that an error occured reading a FAT12 or FAT16
205+// file allocation table. Note that since '0xFFF8' is used for the last cluster return value in the FAT16 implementation
206+// the end-of-file value '0xFFFF' can be used to indicate an error condition.
207+#define CLUSTER_FAIL_FAT16 0xFFFF
208+
209+
210+
211+#ifdef SUPPORT_FAT32
212+ // Summary: A macro to indicate the last cluster value for FAT32
213+ // Description: The LAST_CLUSTER_FAT32 macro is used when reading the FAT to indicate that the next FAT32 entry for a file contains
214+ // the end-of-file value.
215+ #define LAST_CLUSTER_FAT32 0x0FFFFFF8
216+
217+ // Summary: A macro to indicate the last allocatable cluster for FAT32
218+ // Description: The END_CLUSTER_FAT32 value is used as a comparison in FAT32 to determine that the firmware has reached the end of
219+ // the range of allowed allocatable clusters.
220+ #define END_CLUSTER_FAT32 0x0FFFFFF7
221+
222+ // Summary: A macro to indicate the failure of the ReadFAT function
223+ // Description: The CLUSTER_FAIL_FAT32 macro is used by the ReadFAT function to indicate that an error occured reading a FAT32
224+ // file allocation able.
225+ #define CLUSTER_FAIL_FAT32 0x0FFFFFFF
226+
227+#endif
228+
229+// Summary: A macro indicating the number of bytes in a directory entry.
230+// Description: The NUMBER_OF_BYTES_IN_DIR_ENTRY macro represents the number of bytes in one directory entry. It is used to calculate
231+// the number of sectors in the root directory based on information in the boot sector.
232+#define NUMBER_OF_BYTES_IN_DIR_ENTRY 32
233+
234+
235+
236+// Summary: A macro for a deleted dir entry marker.
237+// Description: The DIR_DEL macro is used to mark a directory entry as deleted. When a file is deleted, this value will replace the
238+// first character in the file name, and will indicate that the file the entry points to was deleted.
239+#define DIR_DEL 0xE5
240+
241+// Summary: A macro for the last dir entry marker.
242+// Description: The DIR_EMPTY macro is used to indicate the last entry in a directory. Since entries in use cannot start with a 0 and
243+// deleted entries start with the DIR_DEL character, a 0 will mark the end of the in-use or previously used group of
244+// entries in a directory
245+#define DIR_EMPTY 0
246+
247+
248+
249+// Summary: A macro used to indicate the length of an 8.3 file name
250+// Description: The DIR_NAMESIZE macro is used when validing the name portion of 8.3 filenames
251+#define DIR_NAMESIZE 8
252+
253+// Summary: A macro used to indicate the length of an 8.3 file extension
254+// Description: The DIR_EXTENSION macro is used when validating the extension portion of 8.3 filenames
255+#define DIR_EXTENSION 3
256+
257+// Summary: A macro used to indicate the length of an 8.3 file name and extension
258+// Description: The DIR_NAMECOMP macro is used when validating 8.3 filenames
259+#define DIR_NAMECOMP (DIR_NAMESIZE+DIR_EXTENSION)
260+
261+
262+
263+// Summary: A macro to write a byte to RAM
264+// Description: The RAMwrite macro is used to write a byte of data to a RAM array
265+#define RAMwrite( a, f, d) *(a+f) = d
266+
267+// Summary: A macro to read a byte from RAM
268+// Description: The RAMread macro is used to read a byte of data from a RAM array
269+#define RAMread( a, f) *(a+f)
270+
271+// Summary: A macro to read a 16-bit word from RAM
272+// Description: The RAMreadW macro is used to read two bytes of data from a RAM array
273+#define RAMreadW( a, f) *(WORD *)(a+f)
274+
275+// Summary: A macro to read a 32-bit word from RAM
276+// Description: The RAMreadD macro is used to read four bytes of data from a RAM array
277+#define RAMreadD( a, f) *(DWORD *)(a+f)
278+
279+
280+
281+#ifndef EOF
282+ // Summary: Indicates error conditions or end-of-file conditions
283+ // Description: The EOF macro is used to indicate error conditions in some function calls. It is also used to indicate
284+ // that the end-of-file has been reached.
285+ #define EOF ((int)-1)
286+#endif
287+
288+
289+
290+// Summary: A structure containing information about the device.
291+// Description: The DISK structure contains information about the device being accessed.
292+typedef struct
293+{
294+ BYTE * buffer; // Address of the global data buffer used to read and write file information
295+ DWORD firsts; // Logical block address of the first sector of the FAT partition on the device
296+ DWORD fat; // Logical block address of the FAT
297+ DWORD root; // Logical block address of the root directory
298+ DWORD data; // Logical block address of the data section of the device.
299+ WORD maxroot; // The maximum number of entries in the root directory.
300+ DWORD maxcls; // The maximum number of clusters in the partition.
301+ DWORD sectorSize; // The size of a sector in bytes
302+ DWORD fatsize; // The number of sectors in the FAT
303+ BYTE fatcopy; // The number of copies of the FAT in the partition
304+ BYTE SecPerClus; // The number of sectors per cluster in the data region
305+ BYTE type; // The file system type of the partition (FAT12, FAT16 or FAT32)
306+ BYTE mount; // Device mount flag (TRUE if disk was mounted successfully, FALSE otherwise)
307+#if defined __PIC32MX__ || defined __C30__
308+} __attribute__ ((packed)) DISK;
309+#else
310+} DISK;
311+#endif
312+
313+
314+#ifdef __18CXX
315+ // Summary: A 24-bit data type
316+ // Description: The SWORD macro is used to defined a 24-bit data type. For 16+ bit architectures, this must be represented as
317+ // an array of three bytes.
318+ typedef unsigned short long SWORD;
319+#else
320+ // Summary: A 24-bit data type
321+ // Description: The SWORD macro is used to defined a 24-bit data type. For 16+ bit architectures, this must be represented as
322+ // an array of three bytes.
323+ typedef struct
324+ {
325+ unsigned char array[3];
326+#if defined __PIC32MX__ || defined __C30__
327+ } __attribute__ ((packed)) SWORD;
328+#else
329+ } SWORD;
330+#endif
331+#endif
332+
333+
334+
335+// Summary: A structure containing the bios parameter block for a FAT12 file system (in the boot sector)
336+// Description: The _BPB_FAT12 structure provides a layout of the "bios parameter block" in the boot sector of a FAT12 partition.
337+typedef struct {
338+ SWORD BootSec_JumpCmd; // Jump Command
339+ BYTE BootSec_OEMName[8]; // OEM name
340+ WORD BootSec_BPS; // Number of bytes per sector
341+ BYTE BootSec_SPC; // Number of sectors per cluster
342+ WORD BootSec_ResrvSec; // Number of reserved sectors at the beginning of the partition
343+ BYTE BootSec_FATCount; // Number of FATs on the partition
344+ WORD BootSec_RootDirEnts; // Number of root directory entries
345+ WORD BootSec_TotSec16; // Total number of sectors
346+ BYTE BootSec_MDesc; // Media descriptor
347+ WORD BootSec_SPF; // Number of sectors per FAT
348+ WORD BootSec_SPT; // Number of sectors per track
349+ WORD BootSec_HeadCnt; // Number of heads
350+ DWORD BootSec_HiddenSecCnt; // Number of hidden sectors
351+ DWORD BootSec_Reserved; // Reserved space
352+ BYTE BootSec_DriveNum; // Drive number
353+ BYTE BootSec_Reserved2; // Reserved space
354+ BYTE BootSec_BootSig; // Boot signature - equal to 0x29
355+ BYTE BootSec_VolID[4]; // Volume ID
356+ BYTE BootSec_VolLabel[11]; // Volume Label
357+ BYTE BootSec_FSType[8]; // File system type in ASCII. Not used for determination
358+#if defined __PIC32MX__ || defined __C30__
359+ } __attribute__ ((packed)) _BPB_FAT12;
360+#else
361+ } _BPB_FAT12;
362+#endif
363+
364+// Summary: A structure containing the bios parameter block for a FAT16 file system (in the boot sector)
365+// Description: The _BPB_FAT16 structure provides a layout of the "bios parameter block" in the boot sector of a FAT16 partition.
366+typedef struct {
367+ SWORD BootSec_JumpCmd; // Jump Command
368+ BYTE BootSec_OEMName[8]; // OEM name
369+ WORD BootSec_BPS; // Number of bytes per sector
370+ BYTE BootSec_SPC; // Number of sectors per cluster
371+ WORD BootSec_ResrvSec; // Number of reserved sectors at the beginning of the partition
372+ BYTE BootSec_FATCount; // Number of FATs on the partition
373+ WORD BootSec_RootDirEnts; // Number of root directory entries
374+ WORD BootSec_TotSec16; // Total number of sectors
375+ BYTE BootSec_MDesc; // Media descriptor
376+ WORD BootSec_SPF; // Number of sectors per FAT
377+ WORD BootSec_SPT; // Number of sectors per track
378+ WORD BootSec_HeadCnt; // Number of heads
379+ DWORD BootSec_HiddenSecCnt; // Number of hidden sectors
380+ DWORD BootSec_TotSec32; // Total sector count (32 bits)
381+ BYTE BootSec_DriveNum; // Drive number
382+ BYTE BootSec_Reserved; // Reserved space
383+ BYTE BootSec_BootSig; // Boot signature - equal to 0x29
384+ BYTE BootSec_VolID[4]; // Volume ID
385+ BYTE BootSec_VolLabel[11]; // Volume Label
386+ BYTE BootSec_FSType[8]; // File system type in ASCII. Not used for determination
387+#if defined __PIC32MX__ || defined __C30__
388+ } __attribute__ ((packed)) _BPB_FAT16;
389+#else
390+ } _BPB_FAT16;
391+#endif
392+
393+// Summary: A structure containing the bios parameter block for a FAT32 file system (in the boot sector)
394+// Description: The _BPB_FAT32 structure provides a layout of the "bios parameter block" in the boot sector of a FAT32 partition.
395+typedef struct {
396+ SWORD BootSec_jmpBoot; // Jump Command
397+ BYTE BootSec_OEMName[8]; // OEM name
398+ WORD BootSec_BytsPerSec; // Number of bytes per sector
399+ BYTE BootSec_SecPerClus; // Number of sectors per cluster
400+ WORD BootSec_RsvdSecCnt; // Number of reserved sectors at the beginning of the partition
401+ BYTE BootSec_NumFATs; // Number of FATs on the partition
402+ WORD BootSec_RootEntCnt; // Number of root directory entries
403+ WORD BootSec_TotSec16; // Total number of sectors
404+ BYTE BootSec_Media; // Media descriptor
405+ WORD BootSec_FATSz16; // Number of sectors per FAT
406+ WORD BootSec_SecPerTrk; // Number of sectors per track
407+ WORD BootSec_NumHeads; // Number of heads
408+ DWORD BootSec_HiddSec; // Number of hidden sectors
409+ DWORD BootSec_TotSec32; // Total sector count (32 bits)
410+ DWORD BootSec_FATSz32; // Sectors per FAT (32 bits)
411+ WORD BootSec_ExtFlags; // Presently active FAT. Defined by bits 0-3 if bit 7 is 1.
412+ WORD BootSec_FSVers; // FAT32 filesystem version. Should be 0:0
413+ DWORD BootSec_RootClus; // Start cluster of the root directory (should be 2)
414+ WORD BootSec_FSInfo; // File system information
415+ WORD BootSec_BkBootSec; // Backup boot sector address.
416+ BYTE BootSec_Reserved[12]; // Reserved space
417+ BYTE BootSec_DrvNum; // Drive number
418+ BYTE BootSec_Reserved1; // Reserved space
419+ BYTE BootSec_BootSig; // Boot signature - 0x29
420+ BYTE BootSec_VolID[4]; // Volume ID
421+ BYTE BootSec_VolLab[11]; // Volume Label
422+ BYTE BootSec_FilSysType[8]; // File system type in ASCII. Not used for determination
423+#if defined __PIC32MX__ || defined __C30__
424+ } __attribute__ ((packed)) _BPB_FAT32;
425+#else
426+ } _BPB_FAT32;
427+#endif
428+
429+
430+// Description: A macro for the boot sector bytes per sector value offset
431+#define BSI_BPS 11
432+
433+// Description: A macro for the boot sector sector per cluster value offset
434+#define BSI_SPC 13
435+
436+// Description: A macro for the boot sector reserved sector count value offset
437+#define BSI_RESRVSEC 14
438+
439+// Description: A macro for the boot sector FAT count value offset
440+#define BSI_FATCOUNT 16
441+
442+// Description: A macro for the boot sector root directory entry count value offset
443+#define BSI_ROOTDIRENTS 17
444+
445+// Description: A macro for the boot sector 16-bit total sector count value offset
446+#define BSI_TOTSEC16 19
447+
448+// Description: A macro for the boot sector sectors per FAT value offset
449+#define BSI_SPF 22
450+
451+// Description: A macro for the boot sector 32-bit total sector count value offset
452+#define BSI_TOTSEC32 32
453+
454+// Description: A macro for the boot sector boot signature offset
455+#define BSI_BOOTSIG 38
456+
457+// Description: A macro for the boot sector file system type string offset
458+#define BSI_FSTYPE 54
459+
460+// Description: A macro for the boot sector 32-bit sector per FAT value offset
461+#define BSI_FATSZ32 36
462+
463+// Description: A macro for the boot sector start cluster of root directory value offset
464+#define BSI_ROOTCLUS 44
465+
466+// Description: A macro for the FAT32 boot sector boot signature offset
467+#define BSI_FAT32_BOOTSIG 66
468+
469+// Description: A macro for the FAT32 boot sector file system type string offset
470+#define BSI_FAT32_FSTYPE 82
471+
472+
473+
474+// Summary: A partition table entry structure.
475+// Description: The PTE_MBR structure contains values found in a partition table entry in the MBR of a device.
476+typedef struct
477+{
478+ BYTE PTE_BootDes; // The boot descriptor (should be 0x00 in a non-bootable device)
479+ SWORD PTE_FrstPartSect; // The cylinder-head-sector address of the first sector of the partition
480+ BYTE PTE_FSDesc; // The file system descriptor
481+ SWORD PTE_LstPartSect; // The cylinder-head-sector address of the last sector of the partition
482+ DWORD PTE_FrstSect; // The logical block address of the first sector of the partition
483+ DWORD PTE_NumSect; // The number of sectors in a partition
484+#if defined __PIC32MX__ || defined __C30__
485+ } __attribute__ ((packed)) PTE_MBR;
486+#else
487+ } PTE_MBR;
488+#endif
489+
490+
491+// Summary: A structure of the organization of a master boot record.
492+// Description: The _PT_MBR structure has the same form as a master boot record. When the MBR is loaded from the device, it will
493+// be cast as a _PT_MBR structure so the MBR elements can be accessed.
494+typedef struct
495+{
496+ BYTE ConsChkRtn[446]; // Boot code
497+ PTE_MBR Partition0; // The first partition table entry
498+ PTE_MBR Partition1; // The second partition table entry
499+ PTE_MBR Partition2; // The third partition table entry
500+ PTE_MBR Partition3; // The fourth partition table entry
501+ BYTE Signature0; // MBR signature code - equal to 0x55
502+ BYTE Signature1; // MBR signature code - equal to 0xAA
503+#if defined __PIC32MX__ || defined __C30__
504+}__attribute__((packed)) _PT_MBR;
505+#else
506+}_PT_MBR;
507+#endif
508+
509+// Summary: A pointer to a _PT_MBR structure
510+// Description: The PT_MBR pointer points to a _PT_MBR structure.
511+typedef _PT_MBR * PT_MBR;
512+
513+
514+
515+// Summary: A structure of the organization of a boot sector.
516+// Description: The _BootSec structure has the same form as a boot sector. When the boot sector is loaded from the device, it will
517+// be cast as a _BootSec structure so the boot sector elements can be accessed.
518+typedef struct
519+{
520+ // A union of different bios parameter blocks
521+ union
522+ {
523+ _BPB_FAT32 FAT_32;
524+ _BPB_FAT16 FAT_16;
525+ _BPB_FAT12 FAT_12;
526+ }FAT;
527+ BYTE Reserved[512-sizeof(_BPB_FAT32)-2]; // Reserved space
528+ BYTE Signature0; // Boot sector signature code - equal to 0x55
529+ BYTE Signature1; // Boot sector signature code - equal to 0xAA
530+#if defined __PIC32MX__ || defined __C30__
531+ } __attribute__ ((packed)) _BootSec;
532+#else
533+ } _BootSec;
534+#endif
535+
536+// Summary: A pointer to a _BootSec structure
537+// Description: The BootSec pointer points to a _BootSec structure.
538+typedef _BootSec * BootSec;
539+
540+
541+
542+// Summary: A macro indicating the offset for the master boot record
543+// Description: FO_MBR is a macro that indicates the addresss of the master boot record on the device. When the device is initialized
544+// this sector will be read
545+#define FO_MBR 0L
546+
547+
548+
549+// Summary: A macro for the first boot sector/MBR signature byte
550+// Description: The FAT_GOOD_SIGN_0 macro is used to determine that the first byte of the MBR or boot sector signature code is correct
551+#define FAT_GOOD_SIGN_0 0x55
552+
553+// Summary: A macro for the second boot sector/MBR signature byte
554+// Description: The FAT_GOOD_SIGN_1 macro is used to determine that the second byte of the MBR or boot sector signature code is correct
555+#define FAT_GOOD_SIGN_1 0xAA
556+
557+
558+typedef struct
559+{
560+ BYTE errorCode;
561+ union
562+ {
563+ BYTE value;
564+ struct
565+ {
566+ BYTE sectorSize : 1;
567+ BYTE maxLUN : 1;
568+ } bits;
569+ } validityFlags;
570+
571+ WORD sectorSize;
572+ BYTE maxLUN;
573+} MEDIA_INFORMATION;
574+
575+typedef enum
576+{
577+ MEDIA_NO_ERROR, // No errors
578+ MEDIA_DEVICE_NOT_PRESENT, // The requested device is not present
579+ MEDIA_CANNOT_INITIALIZE // Cannot initialize media
580+} MEDIA_ERRORS;
581+
582+
583+
584+
585+/*******************************************************************/
586+/* Strunctures and defines */
587+/*******************************************************************/
588+
589+#ifndef FALSE
590+ // Summary: False value
591+ // Description: This macro will indicate that a condition is false.
592+ #define FALSE 0
593+#endif
594+#ifndef TRUE
595+ // Summary: True value
596+ // Description: This macro will indicate that a condition is true.
597+ #define TRUE !FALSE // True value
598+#endif
599+
600+
601+
602+
603+#ifndef SEEK_SET
604+ // Summary: Macro for the FSfseek SEEK_SET base location.
605+ // Description: Functions as an input for FSfseek that specifies that the position in the file will be changed
606+ // relative to the beginning of the file.
607+ #define SEEK_SET 0
608+
609+#endif
610+#ifndef SEEK_CUR
611+
612+ // Summary: Macro for the FSfseek SEEK_CUR base location.
613+ // Description: Functions as an input for FSfseek that specifies that the position in the file will be changed
614+ // relative to the current location of the file
615+ #define SEEK_CUR 1
616+
617+#endif
618+#ifndef SEEK_END
619+
620+ // Summary: Macro for the FSfseek SEEK_END base location
621+ // Description: Functions as an input for FSfseek that specifies that the position in the file will be changed
622+ // relative to the end of the file. For this macro, the offset value will be subtracted from
623+ // the end location of the file by default.
624+ #define SEEK_END 2
625+
626+#endif
627+
628+
629+
630+
631+// Summary: Macro for the FSfopen FS_APPEND mode
632+// Description: If this macro is specified as the mode argument in a call of FSfopen, the file being opened will
633+// be created if it doesn't exist. If it does exist, it's file information will be loaded and the
634+// current location in the file will be set to the end. The user will then be able to write to the file.
635+#define FS_APPEND "a"
636+#define APPEND "a" //deprecated
637+
638+// Summary: Macro for the FSfopen FS_WRITE mode
639+// Description: If this macro is specified as the mode argument in a call of FSfopen, the file being opened will
640+// be created if it doesn't exist. If it does exist, it will be erased and replaced by an empty file
641+// of the same name. The user will then be able to write to the file.
642+#define FS_WRITE "w"
643+#define WRITE "w" //deprecated
644+
645+// Summary: Macro for the FSfopen FS_READ mode
646+// Description: If this macro is specified as the mode argument in a call of FSfopen, the file information for the
647+// specified file will be loaded. If the file does not exist, the FSfopen function will fail. The user
648+// will then be able to read from the file.
649+#define FS_READ "r"
650+#if defined(__32MX795F512L__)
651+ #warning FSfopen must use "r" and not READ as input on this device
652+#else
653+ #define READ "r" //deprecated
654+#endif
655+
656+// Summary: Macro for the FSfopen FS_APPEND+ mode
657+// Description: If this macro is specified as the mode argument in a call of FSfopen, the file being opened will
658+// be created if it doesn't exist. If it does exist, it's file information will be loaded and the
659+// current location in the file will be set to the end. The user will then be able to write to the file
660+// or read from the file.
661+#define FS_APPENDPLUS "a+"
662+#define APPENDPLUS "a+" //deprecated
663+
664+// Summary: Macro for the FSfopen FS_WRITE+ mode
665+// Description: If this macro is specified as the mode argument in a call of FSfopen, the file being opened will
666+// be created if it doesn't exist. If it does exist, it will be erased and replaced by an empty file
667+// of the same name. The user will then be able to write to the file or read from the file.
668+#define FS_WRITEPLUS "w+"
669+#define WRITEPLUS "w+" //deprecated
670+
671+// Summary: Macro for the FSfopen FS_READ+ mode
672+// Description: If this macro is specified as the mode argument in a call of FSfopen, the file information for the
673+// specified file will be loaded. If the file does not exist, the FSfopen function will fail. The user
674+// will then be able to read from the file or write to the file.
675+#define FS_READPLUS "r+"
676+#define READPLUS "r+" //deprecated
677+
678+
679+
680+#ifndef intmax_t
681+ #ifdef __PIC24F__
682+ // Summary: A data type indicating the maximum integer size in an architecture
683+ // Description: The intmax_t data type refers to the maximum-sized data type on any given architecture. This
684+ // data type can be specified as a format specifier size specification for the FSfprintf function.
685+ #define intmax_t long long
686+ #elif defined __PIC24H__
687+ #define intmax_t long long
688+ #elif defined __dsPIC30F__
689+ #define intmax_t long long
690+ #elif defined __dsPIC33F__
691+ #define intmax_t long long
692+ #endif
693+#endif
694+
695+
696+
697+// Summary: Indicates flag conditions for a file object
698+// Description: The FILEFLAGS structure is used to indicate conditions in a file. It contains three flags: 'write' indicates
699+// that the file was opened in a mode that allows writes, 'read' indicates that the file was opened in a mode
700+// that allows reads, and 'FileWriteEOF' indicates that additional data that is written to the file will increase
701+// the file size.
702+typedef struct
703+{
704+ unsigned write :1; // Indicates a file was opened in a mode that allows writes
705+ unsigned read :1; // Indicates a file was opened in a mode that allows reads
706+ unsigned FileWriteEOF :1; // Indicates the current position in a file is at the end of the file
707+}FILEFLAGS;
708+
709+
710+
711+// Summary: Indicates how to search for file entries in the FILEfind function
712+// Description: The values in the SEARCH_TYPE enumeration are used internally by the library to indicate how the FILEfind function
713+// how to perform a search. The 'LOOK_FOR_EMPTY_ENTRY' value indicates that FILEfind should search for an empty file entry.
714+// The 'LOOK_FOR_MATCHING_ENTRY' value indicates that FILEfind should search for an entry that matches the FSFILE object
715+// that was passed into the FILEfind function.
716+typedef enum{
717+ LOOK_FOR_EMPTY_ENTRY = 0,
718+ LOOK_FOR_MATCHING_ENTRY
719+} SEARCH_TYPE;
720+
721+
722+
723+// Summary: Macro indicating the length of a 8.3 file name
724+// Description: The TOTAL_FILE_SIZE_8P3 macro indicates the maximum number of characters in an 8.3 file name. This value includes
725+// 8 characters for the name, three for the extentsion, and 1 for the radix ('.')
726+#define TOTAL_FILE_SIZE_8P3 (8+3+1)
727+#define TOTAL_FILE_SIZE TOTAL_FILE_SIZE_8P3
728+
729+// Summary: Macro indicating the max length of a LFN file name
730+// Description: The MAX_FILE_NAME_LENGTH_LFN macro indicates the maximum number of characters in an LFN file name.
731+#define MAX_FILE_NAME_LENGTH_LFN 256
732+
733+// Summary: A mask that indicates the limit of directory entries in a sector
734+// Description: The MASK_MAX_FILE_ENTRY_LIMIT_BITS is used to indicate to the Cache_File_Entry function that a new sector needs to
735+// be loaded.
736+#define MASK_MAX_FILE_ENTRY_LIMIT_BITS 0x0f
737+
738+// Summary: Value used for shift operations to calculate the sector offset in a directory
739+// Description: The VALUE_BASED_ON_ENTRIES_PER_CLUSTER macro is used to calculate sector offsets for directories. The position of the
740+// entry is shifted by 4 bits (divided by 16, since there are 16 entries in a sector) to calculate how many sectors a
741+// specified entry is offset from the beginning of the directory.
742+#define VALUE_BASED_ON_ENTRIES_PER_CLUSTER 4
743+
744+// Summary: A value that will indicate that a dotdot directory entry points to the root.
745+// Description: The VALUE_DOTDOT_CLUSTER_VALUE_FOR_ROOT macro is used as an absolute address when writing information to a dotdot entry
746+// in a newly created directory. If a dotdot entry points to the root directory, it's cluster value must be set to 0,
747+// regardless of the actual cluster number of the root directory.
748+#define VALUE_DOTDOT_CLUSTER_VALUE_FOR_ROOT 0
749+
750+// Summary: MAcro indicating the length of an 8.3 file name in a directory entry
751+// Description: The FILE_NAME_SIZE_8P3 macro indicates the number of characters that an 8.3 file name will take up when packed in
752+// a directory entry. This value includes 8 characters for the name and 3 for the extension. Note that the radix is not
753+// stored in the directory entry.
754+#define FILE_NAME_SIZE_8P3 11
755+#define FILE_NAME_SIZE FILE_NAME_SIZE_8P3
756+
757+
758+// Summary: Contains file information and is used to indicate which file to access.
759+// Description: The FSFILE structure is used to hold file information for an open file as it's being modified or accessed. A pointer to
760+// an open file's FSFILE structure will be passeed to any library function that will modify that file.
761+typedef struct
762+{
763+ DISK * dsk; // Pointer to a DISK structure
764+ DWORD cluster; // The first cluster of the file
765+ DWORD ccls; // The current cluster of the file
766+ WORD sec; // The current sector in the current cluster of the file
767+ WORD pos; // The position in the current sector
768+ DWORD seek; // The absolute position in the file
769+ DWORD size; // The size of the file
770+ FILEFLAGS flags; // A structure containing file flags
771+ WORD time; // The file's last update time
772+ WORD date; // The file's last update date
773+ char name[FILE_NAME_SIZE_8P3]; // The short name of the file
774+ #ifdef SUPPORT_LFN
775+ BOOL AsciiEncodingType; // Ascii file name or Non-Ascii file name indicator
776+ unsigned short int *utf16LFNptr; // Pointer to long file name in UTF16 format
777+ unsigned short int utf16LFNlength; // LFN length in terms of words including the NULL word at the last.
778+ #endif
779+ WORD entry; // The position of the file's directory entry in it's directory
780+ WORD chk; // File structure checksum
781+ WORD attributes; // The file attributes
782+ DWORD dirclus; // The base cluster of the file's directory
783+ DWORD dirccls; // The current cluster of the file's directory
784+} FSFILE;
785+
786+/* Summary: Possible results of the FSGetDiskProperties() function.
787+** Description: See the FSGetDiskProperties() function for more information.
788+*/
789+typedef enum
790+{
791+ FS_GET_PROPERTIES_NO_ERRORS = 0,
792+ FS_GET_PROPERTIES_DISK_NOT_MOUNTED,
793+ FS_GET_PROPERTIES_CLUSTER_FAILURE,
794+ FS_GET_PROPERTIES_STILL_WORKING = 0xFF
795+} FS_DISK_ERRORS;
796+
797+
798+/* Summary: Contains the disk search information, intermediate values, and results
799+** Description: This structure is used in conjunction with the FSGetDiskProperties()
800+** function. See that function for more information about the usage.
801+*/
802+typedef struct
803+{
804+ DISK * disk; /* pointer to the disk we are searching */
805+ BOOL new_request; /* is this a new request or a continued request */
806+ FS_DISK_ERRORS properties_status; /* status of the last call of the function */
807+
808+ struct
809+ {
810+ BYTE disk_format; /* disk format: FAT12, FAT16, FAT32 */
811+ WORD sector_size; /* sector size of the drive */
812+ BYTE sectors_per_cluster; /* number of sectors per cluster */
813+ DWORD total_clusters; /* the number of total clusters on the drive */
814+ DWORD free_clusters; /* the number of free (unused) clusters on drive */
815+ } results; /* the results of the current search */
816+
817+ struct
818+ {
819+ DWORD c;
820+ DWORD curcls;
821+ DWORD EndClusterLimit;
822+ DWORD ClusterFailValue;
823+ } private; /* intermediate values used to continue searches. This
824+ member should be used only by the FSGetDiskProperties()
825+ function */
826+
827+} FS_DISK_PROPERTIES;
828+
829+// Summary: A structure used for searching for files on a device.
830+// Description: The SearchRec structure is used when searching for file on a device. It contains parameters that will be loaded with
831+// file information when a file is found. It also contains the parameters that the user searched for, allowing further
832+// searches to be perfomed in the same directory for additional files that meet the specified criteria.
833+typedef struct
834+{
835+ char filename[FILE_NAME_SIZE_8P3 + 2]; // The name of the file that has been found
836+ unsigned char attributes; // The attributes of the file that has been found
837+ unsigned long filesize; // The size of the file that has been found
838+ unsigned long timestamp; // The last modified time of the file that has been found (create time for directories)
839+ #ifdef SUPPORT_LFN
840+ BOOL AsciiEncodingType; // Ascii file name or Non-Ascii file name indicator
841+ unsigned short int *utf16LFNfound; // Pointer to long file name found in UTF16 format
842+ unsigned short int utf16LFNfoundLength; // LFN Found length in terms of words including the NULL word at the last.
843+ #endif
844+ unsigned int entry; // The directory entry of the last file found that matches the specified attributes. (Internal use only)
845+ char searchname[FILE_NAME_SIZE_8P3 + 2]; // The 8.3 format name specified when the user began the search. (Internal use only)
846+ unsigned char searchattr; // The attributes specified when the user began the search. (Internal use only)
847+ unsigned long cwdclus; // The directory that this search was performed in. (Internal use only)
848+ unsigned char initialized; // Check to determine if the structure was initialized by FindFirst (Internal use only)
849+} SearchRec;
850+
851+
852+/***************************************************************************
853+* Prototypes *
854+***************************************************************************/
855+
856+
857+
858+
859+/*************************************************************************
860+ Function:
861+ int FSInit(void)
862+ Summary:
863+ Function to initialize the device.
864+ Conditions:
865+ The physical device should be connected to the microcontroller.
866+ Input:
867+ None
868+ Return Values:
869+ TRUE - Initialization successful
870+ FALSE - Initialization unsuccessful
871+ Side Effects:
872+ The FSerrno variable will be changed.
873+ Description:
874+ Initializes the static or dynamic memory slots for holding file
875+ structures. Initializes the device with the DISKmount function. Loads
876+ MBR and boot sector information. Initializes the current working
877+ directory to the root directory for the device if directory support
878+ is enabled.
879+ Remarks:
880+ None
881+ *************************************************************************/
882+
883+int FSInit(void);
884+
885+
886+/*********************************************************************
887+ Function:
888+ FSFILE * FSfopen (const char * fileName, const char *mode)
889+ Summary:
890+ Open a Ascii file
891+ Conditions:
892+ For read modes, file exists; FSInit performed
893+ Input:
894+ fileName - The name of the file to open
895+ mode -
896+ - WRITE - Create a new file or replace an existing file
897+ - READ - Read data from an existing file
898+ - APPEND - Append data to an existing file
899+ - WRITEPLUS - Create a new file or replace an existing file (reads also enabled)
900+ - READPLUS - Read data from an existing file (writes also enabled)
901+ - APPENDPLUS - Append data to an existing file (reads also enabled)
902+ Return Values:
903+ FSFILE * - The pointer to the file object
904+ NULL - The file could not be opened
905+ Side Effects:
906+ The FSerrno variable will be changed.
907+ Description:
908+ This function will open a file or directory. First, RAM in the
909+ dynamic heap or static array will be allocated to a new FSFILE object.
910+ Then, the specified file name will be formatted to ensure that it's
911+ in 8.3 format or LFN format. Next, the FILEfind function will be used
912+ to search for the specified file name. If the name is found, one of three
913+ things will happen: if the file was opened in read mode, its file
914+ info will be loaded using the FILEopen function; if it was opened in
915+ write mode, it will be erased, and a new file will be constructed in
916+ its place; if it was opened in append mode, its file info will be
917+ loaded with FILEopen and the current location will be moved to the
918+ end of the file using the FSfseek function. If the file was not
919+ found by FILEfind, a new file will be created if the mode was specified as
920+ a write or append mode. In these cases, a pointer to the heap or
921+ static FSFILE object array will be returned. If the file was not
922+ found and the mode was specified as a read mode, the memory
923+ allocated to the file will be freed and the NULL pointer value
924+ will be returned.
925+ Remarks:
926+ None.
927+ *********************************************************************/
928+
929+FSFILE * FSfopen(const char * fileName, const char *mode);
930+
931+#ifdef SUPPORT_LFN
932+/*********************************************************************
933+ Function:
934+ FSFILE * wFSfopen (const unsigned short int * fileName, const char *mode)
935+ Summary:
936+ Open a UTF16 file.
937+ Conditions:
938+ For read modes, file exists; FSInit performed
939+ Input:
940+ fileName - The name of the file to open
941+ mode -
942+ - WRITE - Create a new file or replace an existing file
943+ - READ - Read data from an existing file
944+ - APPEND - Append data to an existing file
945+ - WRITEPLUS - Create a new file or replace an existing file (reads also enabled)
946+ - READPLUS - Read data from an existing file (writes also enabled)
947+ - APPENDPLUS - Append data to an existing file (reads also enabled)
948+ Return Values:
949+ FSFILE * - The pointer to the file object
950+ NULL - The file could not be opened
951+ Side Effects:
952+ The FSerrno variable will be changed.
953+ Description:
954+ This function will open a file or directory. First, RAM in the
955+ dynamic heap or static array will be allocated to a new FSFILE object.
956+ Then, the specified file name will be formatted to ensure that it's
957+ in 8.3 format or LFN format. Next, the FILEfind function will be used
958+ to search for the specified file name. If the name is found, one of three
959+ things will happen: if the file was opened in read mode, its file
960+ info will be loaded using the FILEopen function; if it was opened in
961+ write mode, it will be erased, and a new file will be constructed in
962+ its place; if it was opened in append mode, its file info will be
963+ loaded with FILEopen and the current location will be moved to the
964+ end of the file using the FSfseek function. If the file was not
965+ found by FILEfind, a new file will be created if the mode was specified as
966+ a write or append mode. In these cases, a pointer to the heap or
967+ static FSFILE object array will be returned. If the file was not
968+ found and the mode was specified as a read mode, the memory
969+ allocated to the file will be freed and the NULL pointer value
970+ will be returned.
971+ Remarks:
972+ None.
973+ *********************************************************************/
974+
975+FSFILE * wFSfopen(const unsigned short int * fileName, const char *mode);
976+#endif
977+
978+#ifdef ALLOW_PGMFUNCTIONS
979+
980+/******************************************************************************
981+ Function:
982+ FSFILE * FSfopenpgm(const rom char * fileName, const rom char *mode)
983+ Summary:
984+ Open a Ascii file named with a ROM string on PIC18
985+ Conditions:
986+ For read modes, file exists; FSInit performed
987+ Input:
988+ fileName - The name of the file to be opened (ROM)
989+ mode - The mode the file will be opened in (ROM)
990+ Return Values:
991+ FSFILE * - A pointer to the file object
992+ NULL - File could not be opened
993+ Side Effects:
994+ The FSerrno variable will be changed.
995+ Description:
996+ The FSfopenpgm function will copy a PIC18 ROM fileName and mode argument
997+ into RAM arrays, and then pass those arrays to the FSfopen function.
998+ Remarks:
999+ This function is for use with PIC18 when passing arguments in ROM.
1000+ ******************************************************************************/
1001+
1002+ FSFILE * FSfopenpgm(const rom char * fileName, const rom char *mode);
1003+
1004+
1005+/**************************************************************************************
1006+ Function:
1007+ int FindFirstpgm (const char * fileName, unsigned int attr, SearchRec * rec)
1008+ Summary:
1009+ Find a file named with a ROM string on PIC18
1010+ Conditions:
1011+ None
1012+ Input:
1013+ fileName - The name of the file to be found (ROM)
1014+ attr - The attributes of the file to be found
1015+ rec - Pointer to a search record to store the file info in
1016+ Return Values:
1017+ 0 - File was found
1018+ -1 - No file matching the given parameters was found
1019+ Side Effects:
1020+ Search criteria from previous FindFirstpgm call on passed SearchRec object
1021+ will be lost.The FSerrno variable will be changed.
1022+ Description:
1023+ The FindFirstpgm function will copy a PIC18 ROM fileName argument
1024+ into a RAM array, and then pass that array to the FindFirst function.
1025+ Remarks:
1026+ Call FindFirstpgm or FindFirst before calling FindNext.
1027+ This function is for use with PIC18 when passing arguments in ROM.
1028+ **************************************************************************************/
1029+
1030+ int FindFirstpgm (const rom char * fileName, unsigned int attr, SearchRec * rec);
1031+
1032+
1033+/**************************************************************************
1034+ Function:
1035+ int FSchdirpgm (const rom char * path)
1036+ Summary:
1037+ Changed the CWD with a path in ROM on PIC18
1038+ Conditions:
1039+ None
1040+ Input:
1041+ path - The path of the directory to change to (ROM)
1042+ Return Values:
1043+ 0 - The current working directory was changed successfully
1044+ EOF - The current working directory could not be changed
1045+ Side Effects:
1046+ The current working directory may be changed. The FSerrno variable will
1047+ be changed.
1048+ Description:
1049+ The FSchdirpgm function passes a PIC18 ROM path pointer to the
1050+ chdirhelper function.
1051+ Remarks:
1052+ This function is for use with PIC18 when passing arguments in ROM
1053+ **************************************************************************/
1054+
1055+ int FSchdirpgm (const rom char * path);
1056+
1057+ #ifdef ALLOW_WRITES
1058+
1059+
1060+/*************************************************************
1061+ Function:
1062+ int FSremovepgm (const rom char * fileName)
1063+ Summary:
1064+ Delete a file named with a ROM string on PIC18
1065+ Conditions:
1066+ File not opened; file exists
1067+ Input:
1068+ fileName - The name of the file to be deleted (ROM)
1069+ Return Values:
1070+ 0 - File was removed successfully
1071+ -1 - File could not be removed
1072+ Side Effects:
1073+ The FSerrno variable will be changed.
1074+ Description:
1075+ The FSremovepgm function will copy a PIC18 ROM fileName argument
1076+ into a RAM array, and then pass that array to the FSremove function.
1077+ Remarks:
1078+ This function is for use with PIC18 when passing arguments in ROM.
1079+ *************************************************************/
1080+
1081+ int FSremovepgm (const rom char * fileName);
1082+
1083+
1084+/**************************************************************************
1085+ Function:
1086+ int FSmkdirpgm (const rom char * path)
1087+ Summary:
1088+ Create a directory with a path in ROM on PIC18
1089+ Conditions:
1090+ None
1091+ Input:
1092+ path - The path of directories to create (ROM)
1093+ Return Values:
1094+ 0 - The specified directory was created successfully
1095+ EOF - The specified directory could not be created
1096+ Side Effects:
1097+ Will create all non-existent directories in the path. The FSerrno
1098+ variable will be changed.
1099+ Description:
1100+ The FSmkdirpgm function passes a PIC18 ROM path pointer to the
1101+ mkdirhelper function.
1102+ Remarks:
1103+ This function is for use with PIC18 when passing arugments in ROM
1104+ **************************************************************************/
1105+
1106+ int FSmkdirpgm (const rom char * path);
1107+
1108+
1109+/**************************************************************************
1110+ Function:
1111+ int FSrmdirpgm (const rom char * path)
1112+ Summary:
1113+ Delete a directory with a path in ROM on PIC18
1114+ Conditions:
1115+ None.
1116+ Input:
1117+ path - The path of the directory to remove (ROM)
1118+ rmsubdirs -
1119+ - TRUE - All sub-dirs and files in the target dir will be removed
1120+ - FALSE - FSrmdir will not remove non-empty directories
1121+ Return Values:
1122+ 0 - The specified directory was deleted successfully
1123+ EOF - The specified directory could not be deleted
1124+ Side Effects:
1125+ The FSerrno variable will be changed.
1126+ Description:
1127+ The FSrmdirpgm function passes a PIC18 ROM path pointer to the
1128+ rmdirhelper function.
1129+ Remarks:
1130+ This function is for use with PIC18 when passing arguments in ROM.
1131+ **************************************************************************/
1132+
1133+ int FSrmdirpgm (const rom char * path, unsigned char rmsubdirs);
1134+
1135+
1136+/*****************************************************************
1137+ Function:
1138+ int FSrenamepgm(const rom char * fileName, FSFILE * fo)
1139+ Summary:
1140+ Rename a file named with a ROM string on PIC18
1141+ Conditions:
1142+ File opened.
1143+ Input:
1144+ fileName - The new name of the file (in ROM)
1145+ fo - The file to rename
1146+ Return Values:
1147+ 0 - File renamed successfully
1148+ -1 - File could not be renamed
1149+ Side Effects:
1150+ The FSerrno variable will be changed.
1151+ Description:
1152+ The Fsrenamepgm function will copy the rom fileName specified
1153+ by the user into a RAM array and pass that array into the
1154+ FSrename function.
1155+ Remarks:
1156+ This function is for use with PIC18 when passing arguments in ROM.
1157+ *****************************************************************/
1158+
1159+ int FSrenamepgm (const rom char * fileName, FSFILE * fo);
1160+ #endif
1161+#endif
1162+
1163+
1164+/************************************************************
1165+ Function:
1166+ int FSfclose(FSFILE *fo)
1167+ Summary:
1168+ Update file information and free FSFILE objects
1169+ Conditions:
1170+ File opened
1171+ Input:
1172+ fo - Pointer to the file to close
1173+ Return Values:
1174+ 0 - File closed successfully
1175+ EOF - Error closing the file
1176+ Side Effects:
1177+ The FSerrno variable will be changed.
1178+ Description:
1179+ This function will update the directory entry for the
1180+ file pointed to by 'fo' with the information contained
1181+ in 'fo,' including the new file size and attributes.
1182+ Timestamp information will also be loaded based on the
1183+ method selected by the user and written to the entry
1184+ as the last modified time and date. The file entry will
1185+ then be written to the device. Finally, the memory
1186+ used for the specified file object will be freed from
1187+ the dynamic heap or the array of FSFILE objects.
1188+ Remarks:
1189+ A function to flush data to the device without closing the
1190+ file can be created by removing the portion of this
1191+ function that frees the memory and the line that clears
1192+ the write flag.
1193+ ************************************************************/
1194+
1195+int FSfclose(FSFILE *fo);
1196+
1197+
1198+/*********************************************************
1199+ Function:
1200+ void FSrewind (FSFILE * fo)
1201+ Summary:
1202+ Set the current position in a file to the beginning
1203+ Conditions:
1204+ File opened.
1205+ Input:
1206+ fo - Pointer to file structure
1207+ Return Values:
1208+ None
1209+ Side Effects:
1210+ None.
1211+ Description:
1212+ The FSrewind funciton will reset the position of the
1213+ specified file to the beginning of the file. This
1214+ functionality is faster than using FSfseek to reset
1215+ the position in the file.
1216+ Remarks:
1217+ None.
1218+ *********************************************************/
1219+
1220+void FSrewind (FSFILE *fo);
1221+
1222+
1223+/**************************************************************************
1224+ Function:
1225+ size_t FSfread(void *ptr, size_t size, size_t n, FSFILE *stream)
1226+ Summary:
1227+ Read data from a file
1228+ Conditions:
1229+ File is opened in a read mode
1230+ Input:
1231+ ptr - Destination buffer for read bytes
1232+ size - Size of units in bytes
1233+ n - Number of units to be read
1234+ stream - File to be read from
1235+ Return:
1236+ size_t - number of units read
1237+ Side Effects:
1238+ The FSerrno variable will be changed.
1239+ Description:
1240+ The FSfread function will read data from the specified file. First,
1241+ the appropriate sector of the file is loaded. Then, data is read into
1242+ the specified buffer until the specified number of bytes have been read.
1243+ When a cluster boundary is reached, a new cluster will be loaded. The
1244+ parameters 'size' and 'n' indicate how much data to read. 'Size'
1245+ refers to the size of one object to read (in bytes), and 'n' will refer
1246+ to the number of these objects to read. The value returned will be equal
1247+ to 'n' unless an error occured or the user tried to read beyond the end
1248+ of the file.
1249+ Remarks:
1250+ None.
1251+ **************************************************************************/
1252+
1253+size_t FSfread(void *ptr, size_t size, size_t n, FSFILE *stream);
1254+
1255+
1256+/**********************************************************************
1257+ Function:
1258+ int FSfseek(FSFILE *stream, long offset, int whence)
1259+ Summary:
1260+ Change the current position in a file
1261+ Conditions:
1262+ File opened
1263+ Input:
1264+ stream - Pointer to file structure
1265+ offset - Offset from base location
1266+ whence -
1267+ - SEEK_SET - Seek from start of file
1268+ - SEEK_CUR - Seek from current location
1269+ - SEEK_END - Seek from end of file (subtract offset)
1270+ Return Values:
1271+ 0 - Operation successful
1272+ -1 - Operation unsuccesful
1273+ Side Effects:
1274+ The FSerrno variable will be changed.
1275+ Description:
1276+ The FSfseek function will change the current position in the file to
1277+ one specified by the user. First, an absolute offset is calculated
1278+ using the offset and base location passed in by the user. Then, the
1279+ position variables are updated, and the sector number that corresponds
1280+ to the new location. That sector is then loaded. If the offset
1281+ falls exactly on a cluster boundary, a new cluster will be allocated
1282+ to the file and the position will be set to the first byte of that
1283+ cluster.
1284+ Remarks:
1285+ None
1286+ **********************************************************************/
1287+
1288+int FSfseek(FSFILE *stream, long offset, int whence);
1289+
1290+
1291+/*******************************************************************
1292+ Function:
1293+ long FSftell (FSFILE * fo)
1294+ Summary:
1295+ Determine the current location in a file
1296+ Conditions:
1297+ File opened
1298+ Input:
1299+ fo - Pointer to file structure
1300+ Return: Current location in the file
1301+ Side Effects:
1302+ The FSerrno variable will be changed
1303+ Description:
1304+ The FSftell function will return the current position in the
1305+ file pointed to by 'fo' by returning the 'seek' variable in the
1306+ FSFILE object, which is used to keep track of the absolute
1307+ location of the current position in the file.
1308+ Remarks:
1309+ None
1310+ *******************************************************************/
1311+
1312+long FSftell(FSFILE *fo);
1313+
1314+
1315+/****************************************************
1316+ Function:
1317+ int FSfeof( FSFILE * stream )
1318+ Summary:
1319+ Indicate whether the current file position is at the end
1320+ Conditions:
1321+ File is open in a read mode
1322+ Input:
1323+ stream - Pointer to the target file
1324+ Return Values:
1325+ Non-Zero - EOF reached
1326+ 0 - Not at end of File
1327+ Side Effects:
1328+ The FSerrno variable will be changed.
1329+ Description:
1330+ The FSfeof function will indicate that the end-of-
1331+ file has been reached for the specified file by
1332+ comparing the absolute location in the file to the
1333+ size of the file.
1334+ Remarks:
1335+ None.
1336+ ****************************************************/
1337+
1338+int FSfeof( FSFILE * stream );
1339+
1340+
1341+#ifdef ALLOW_FORMATS
1342+/*******************************************************************
1343+ Function:
1344+ int FSformat (char mode, long int serialNumber, char * volumeID)
1345+ Summary:
1346+ Formats a device
1347+ Conditions:
1348+ The device must possess a valid master boot record.
1349+ Input:
1350+ mode - - 0 - Just erase the FAT and root
1351+ - 1 - Create a new boot sector
1352+ serialNumber - Serial number to write to the card
1353+ volumeID - Name of the card
1354+ Return Values:
1355+ 0 - Format was successful
1356+ EOF - Format was unsuccessful
1357+ Side Effects:
1358+ The FSerrno variable will be changed.
1359+ Description:
1360+ The FSformat function can be used to create a new boot sector
1361+ on a device, based on the information in the master boot record.
1362+ This function will first initialize the I/O pins and the device,
1363+ and then attempts to read the master boot record. If the MBR
1364+ cannot be loaded successfully, the function will fail. Next, if
1365+ the 'mode' argument is specified as '0' the existing boot sector
1366+ information will be loaded. If the 'mode' argument is '1' an
1367+ entirely new boot sector will be constructed using the disk
1368+ values from the master boot record. Once the boot sector has
1369+ been successfully loaded/created, the locations of the FAT and
1370+ root will be loaded from it, and they will be completely
1371+ erased. If the user has specified a volumeID parameter, a
1372+ VOLUME attribute entry will be created in the root directory
1373+ to name the device.
1374+
1375+ FAT12, FAT16 and FAT32 formatting are supported.
1376+
1377+ Based on the number of sectors, the format function automatically
1378+ compute the smallest possible value for the cluster size in order to
1379+ accommodate the physical size of the media. In this case, if a media
1380+ with a big capacity is formatted, the format function may take a very
1381+ long time to write all the FAT tables.
1382+
1383+ Therefore, the FORMAT_SECTORS_PER_CLUSTER macro may be used to
1384+ specify the exact cluster size (in multiples of sector size). This
1385+ macro can be defined in FSconfig.h
1386+
1387+ Remarks:
1388+ Only devices with a sector size of 512 bytes are supported by the
1389+ format function
1390+ *******************************************************************/
1391+
1392+int FSformat (char mode, long int serialNumber, char * volumeID);
1393+#endif
1394+
1395+
1396+#ifdef ALLOW_WRITES
1397+/***************************************************************************
1398+ Function:
1399+ int FSattrib (FSFILE * file, unsigned char attributes)
1400+ Summary:
1401+ Change the attributes of a file
1402+ Conditions:
1403+ File opened
1404+ Input:
1405+ file - Pointer to file structure
1406+ attributes - The attributes to set for the file
1407+ - Attribute - Value - Indications
1408+ - ATTR_READ_ONLY - 0x01 - The read-only attribute
1409+ - ATTR_HIDDEN - 0x02 - The hidden attribute
1410+ - ATTR_SYSTEM - 0x04 - The system attribute
1411+ - ATTR_ARCHIVE - 0x20 - The archive attribute
1412+ Return Values:
1413+ 0 - Attribute change was successful
1414+ -1 - Attribute change was unsuccessful
1415+ Side Effects:
1416+ The FSerrno variable will be changed.
1417+ Description:
1418+ The FSattrib funciton will set the attributes of the specified file
1419+ to the attributes passed in by the user. This function will load the
1420+ file entry, replace the attributes with the ones specified, and write
1421+ the attributes back. If the specified file is a directory, the
1422+ directory attribute will be preserved.
1423+ Remarks:
1424+ None
1425+ ***************************************************************************/
1426+
1427+int FSattrib (FSFILE * file, unsigned char attributes);
1428+
1429+
1430+/***************************************************************
1431+ Function:
1432+ int FSrename (const rom char * fileName, FSFILE * fo)
1433+ Summary:
1434+ Change the Ascii name of a file or directory
1435+ Conditions:
1436+ File opened.
1437+ Input:
1438+ fileName - The new name of the file
1439+ fo - The file to rename
1440+ Return Values:
1441+ 0 - File was renamed successfully
1442+ EOF - File was not renamed
1443+ Side Effects:
1444+ The FSerrno variable will be changed.
1445+ Description:
1446+ The FSrename function will rename a file. First, it will
1447+ search through the current working directory to ensure the
1448+ specified new filename is not already in use. If it isn't,
1449+ the new filename will be written to the file entry of the
1450+ file pointed to by 'fo.'
1451+ Remarks:
1452+ None
1453+ ***************************************************************/
1454+
1455+int FSrename (const char * fileName, FSFILE * fo);
1456+
1457+#ifdef SUPPORT_LFN
1458+/***************************************************************
1459+ Function:
1460+ int wFSrename (const rom unsigned short int * fileName, FSFILE * fo)
1461+ Summary:
1462+ Change the name of a file or directory to the UTF16 input fileName
1463+ Conditions:
1464+ File opened.
1465+ Input:
1466+ fileName - The new name of the file
1467+ fo - The file to rename
1468+ Return Values:
1469+ 0 - File was renamed successfully
1470+ EOF - File was not renamed
1471+ Side Effects:
1472+ The FSerrno variable will be changed.
1473+ Description:
1474+ The wFSrename function will rename a file. First, it will
1475+ search through the current working directory to ensure the
1476+ specified new UTF16 filename is not already in use. If it isn't,
1477+ the new filename will be written to the file entry of the
1478+ file pointed to by 'fo.'
1479+ Remarks:
1480+ None
1481+ ***************************************************************/
1482+
1483+int wFSrename (const unsigned short int * fileName, FSFILE * fo);
1484+#endif
1485+
1486+/*********************************************************************
1487+ Function:
1488+ int FSremove (const char * fileName)
1489+ Summary:
1490+ Delete a Ascii file
1491+ Conditions:
1492+ File not opened, file exists
1493+ Input:
1494+ fileName - Name of the file to erase
1495+ Return Values:
1496+ 0 - File removed
1497+ EOF - File was not removed
1498+ Side Effects:
1499+ The FSerrno variable will be changed.
1500+ Description:
1501+ The FSremove function will attempt to find the specified file with
1502+ the FILEfind function. If the file is found, it will be erased
1503+ using the FILEerase function.The user can also provide ascii alias name
1504+ of the ascii long file name as the input to this function to get it erased
1505+ from the memory.
1506+ Remarks:
1507+ None
1508+ **********************************************************************/
1509+
1510+int FSremove (const char * fileName);
1511+
1512+#ifdef SUPPORT_LFN
1513+/*********************************************************************
1514+ Function:
1515+ int wFSremove (const unsigned short int * fileName)
1516+ Summary:
1517+ Delete a UTF16 file
1518+ Conditions:
1519+ File not opened, file exists
1520+ Input:
1521+ fileName - Name of the file to erase
1522+ Return Values:
1523+ 0 - File removed
1524+ EOF - File was not removed
1525+ Side Effects:
1526+ The FSerrno variable will be changed.
1527+ Description:
1528+ The wFSremove function will attempt to find the specified UTF16 file
1529+ name with the FILEfind function. If the file is found, it will be erased
1530+ using the FILEerase function.
1531+ Remarks:
1532+ None
1533+ **********************************************************************/
1534+
1535+int wFSremove (const unsigned short int * fileName);
1536+#endif
1537+
1538+/*********************************************************************************
1539+ Function:
1540+ size_t FSfwrite(const void *data_to_write, size_t size, size_t n, FSFILE *stream)
1541+ Summary:
1542+ Write data to a file
1543+ Conditions:
1544+ File opened in WRITE, APPEND, WRITE+, APPEND+, READ+ mode
1545+ Input:
1546+ data_to_write - Pointer to source buffer
1547+ size - Size of units in bytes
1548+ n - Number of units to transfer
1549+ stream - Pointer to file structure
1550+ Return:
1551+ size_t - number of units written
1552+ Side Effects:
1553+ The FSerrno variable will be changed.
1554+ Description:
1555+ The FSfwrite function will write data to a file. First, the sector that
1556+ corresponds to the current position in the file will be loaded (if it hasn't
1557+ already been cached in the global data buffer). Data will then be written to
1558+ the device from the specified buffer until the specified amount has been written.
1559+ If the end of a cluster is reached, the next cluster will be loaded, unless
1560+ the end-of-file flag for the specified file has been set. If it has, a new
1561+ cluster will be allocated to the file. Finally, the new position and filesize
1562+ will be stored in the FSFILE object. The parameters 'size' and 'n' indicate how
1563+ much data to write. 'Size' refers to the size of one object to write (in bytes),
1564+ and 'n' will refer to the number of these objects to write. The value returned
1565+ will be equal to 'n' unless an error occured.
1566+ Remarks:
1567+ None.
1568+ *********************************************************************************/
1569+
1570+size_t FSfwrite(const void *data_to_write, size_t size, size_t n, FSFILE *stream);
1571+
1572+#endif
1573+
1574+#ifdef ALLOW_DIRS
1575+
1576+
1577+/**************************************************************************
1578+ Function:
1579+ int FSchdir (char * path)
1580+ Summary:
1581+ Change the current working directory as per the path specified in Ascii format
1582+ Conditions:
1583+ None
1584+ Input:
1585+ path - The path of the directory to change to.
1586+ Return Values:
1587+ 0 - The current working directory was changed successfully
1588+ EOF - The current working directory could not be changed
1589+ Side Effects:
1590+ The current working directory may be changed. The FSerrno variable will
1591+ be changed.
1592+ Description:
1593+ The FSchdir function passes a RAM pointer to the path to the
1594+ chdirhelper function.
1595+ Remarks:
1596+ None
1597+ **************************************************************************/
1598+
1599+int FSchdir (char * path);
1600+
1601+#ifdef SUPPORT_LFN
1602+/**************************************************************************
1603+ Function:
1604+ int wFSchdir (unsigned short int * path)
1605+ Summary:
1606+ Change the current working directory as per the path specified in UTF16 format
1607+ Conditions:
1608+ None
1609+ Input:
1610+ path - The path of the directory to change to.
1611+ Return Values:
1612+ 0 - The current working directory was changed successfully
1613+ EOF - The current working directory could not be changed
1614+ Side Effects:
1615+ The current working directory may be changed. The FSerrno variable will
1616+ be changed.
1617+ Description:
1618+ The FSchdir function passes a RAM pointer to the path to the
1619+ chdirhelper function.
1620+ Remarks:
1621+ None
1622+ **************************************************************************/
1623+
1624+int wFSchdir (unsigned short int * path);
1625+#endif
1626+
1627+/**************************************************************
1628+ Function:
1629+ char * FSgetcwd (char * path, int numchars)
1630+ Summary:
1631+ Get the current working directory path in Ascii format
1632+ Conditions:
1633+ None
1634+ Input:
1635+ path - Pointer to the array to return the cwd name in
1636+ numchars - Number of chars in the path
1637+ Return Values:
1638+ char * - The cwd name string pointer (path or defaultArray)
1639+ NULL - The current working directory name could not be loaded.
1640+ Side Effects:
1641+ The FSerrno variable will be changed
1642+ Description:
1643+ The FSgetcwd function will get the name of the current
1644+ working directory and return it to the user. The name
1645+ will be copied into the buffer pointed to by 'path,'
1646+ starting at the root directory and copying as many chars
1647+ as possible before the end of the buffer. The buffer
1648+ size is indicated by the 'numchars' argument. The first
1649+ thing this function will do is load the name of the current
1650+ working directory, if it isn't already present. This could
1651+ occur if the user switched to the dotdot entry of a
1652+ subdirectory immediately before calling this function. The
1653+ function will then copy the current working directory name
1654+ into the buffer backwards, and insert a backslash character.
1655+ Next, the function will continuously switch to the previous
1656+ directories and copy their names backwards into the buffer
1657+ until it reaches the root. If the buffer overflows, it
1658+ will be treated as a circular buffer, and data will be
1659+ copied over existing characters, starting at the beginning.
1660+ Once the root directory is reached, the text in the buffer
1661+ will be swapped, so that the buffer contains as much of the
1662+ current working directory name as possible, starting at the
1663+ root.
1664+ Remarks:
1665+ None
1666+ **************************************************************/
1667+
1668+char * FSgetcwd (char * path, int numbchars);
1669+
1670+#ifdef SUPPORT_LFN
1671+/**************************************************************
1672+ Function:
1673+ char * wFSgetcwd (unsigned short int * path, int numchars)
1674+ Summary:
1675+ Get the current working directory path in UTF16 format
1676+ Conditions:
1677+ None
1678+ Input:
1679+ path - Pointer to the array to return the cwd name in
1680+ numchars - Number of chars in the path
1681+ Return Values:
1682+ char * - The cwd name string pointer (path or defaultArray)
1683+ NULL - The current working directory name could not be loaded.
1684+ Side Effects:
1685+ The FSerrno variable will be changed
1686+ Description:
1687+ The FSgetcwd function will get the name of the current
1688+ working directory and return it to the user. The name
1689+ will be copied into the buffer pointed to by 'path,'
1690+ starting at the root directory and copying as many chars
1691+ as possible before the end of the buffer. The buffer
1692+ size is indicated by the 'numchars' argument. The first
1693+ thing this function will do is load the name of the current
1694+ working directory, if it isn't already present. This could
1695+ occur if the user switched to the dotdot entry of a
1696+ subdirectory immediately before calling this function. The
1697+ function will then copy the current working directory name
1698+ into the buffer backwards, and insert a backslash character.
1699+ Next, the function will continuously switch to the previous
1700+ directories and copy their names backwards into the buffer
1701+ until it reaches the root. If the buffer overflows, it
1702+ will be treated as a circular buffer, and data will be
1703+ copied over existing characters, starting at the beginning.
1704+ Once the root directory is reached, the text in the buffer
1705+ will be swapped, so that the buffer contains as much of the
1706+ current working directory name as possible, starting at the
1707+ root.
1708+ Remarks:
1709+ None
1710+ **************************************************************/
1711+
1712+char * wFSgetcwd (unsigned short int * path, int numbchars);
1713+#endif
1714+
1715+#ifdef ALLOW_WRITES
1716+
1717+/**************************************************************************
1718+ Function:
1719+ int FSmkdir (char * path)
1720+ Summary:
1721+ Create a directory as per the Ascii input path
1722+ Conditions:
1723+ None
1724+ Input:
1725+ path - The path of directories to create.
1726+ Return Values:
1727+ 0 - The specified directory was created successfully
1728+ EOF - The specified directory could not be created
1729+ Side Effects:
1730+ Will create all non-existent directories in the path. The FSerrno
1731+ variable will be changed.
1732+ Description:
1733+ The FSmkdir function passes a RAM pointer to the path to the
1734+ mkdirhelper function.
1735+ Remarks:
1736+ None
1737+ **************************************************************************/
1738+
1739+int FSmkdir (char * path);
1740+
1741+#ifdef SUPPORT_LFN
1742+/**************************************************************************
1743+ Function:
1744+ int wFSmkdir (unsigned short int * path)
1745+ Summary:
1746+ Create a directory as per the UTF16 input path
1747+ Conditions:
1748+ None
1749+ Input:
1750+ path - The path of directories to create.
1751+ Return Values:
1752+ 0 - The specified directory was created successfully
1753+ EOF - The specified directory could not be created
1754+ Side Effects:
1755+ Will create all non-existent directories in the path. The FSerrno
1756+ variable will be changed.
1757+ Description:
1758+ The wFSmkdir function passes a RAM pointer to the path to the
1759+ mkdirhelper function.
1760+ Remarks:
1761+ None
1762+ **************************************************************************/
1763+
1764+int wFSmkdir (unsigned short int * path);
1765+#endif
1766+
1767+/**************************************************************************
1768+ Function:
1769+ int FSrmdir (char * path)
1770+ Summary:
1771+ Delete a directory as per the Ascii input path
1772+ Conditions:
1773+ None
1774+ Input:
1775+ path - The path of the directory to remove
1776+ rmsubdirs -
1777+ - TRUE - All sub-dirs and files in the target dir will be removed
1778+ - FALSE - FSrmdir will not remove non-empty directories
1779+ Return Values:
1780+ 0 - The specified directory was deleted successfully
1781+ EOF - The specified directory could not be deleted
1782+ Side Effects:
1783+ The FSerrno variable will be changed.
1784+ Description:
1785+ The FSrmdir function passes a RAM pointer to the path to the
1786+ rmdirhelper function.
1787+ Remarks:
1788+ None.
1789+ **************************************************************************/
1790+
1791+int FSrmdir (char * path, unsigned char rmsubdirs);
1792+
1793+#ifdef SUPPORT_LFN
1794+/**************************************************************************
1795+ Function:
1796+ int wFSrmdir (unsigned short int * path, unsigned char rmsubdirs)
1797+ Summary:
1798+ Delete a directory as per the UTF16 input path
1799+ Conditions:
1800+ None
1801+ Input:
1802+ path - The path of the directory to remove
1803+ rmsubdirs -
1804+ - TRUE - All sub-dirs and files in the target dir will be removed
1805+ - FALSE - FSrmdir will not remove non-empty directories
1806+ Return Values:
1807+ 0 - The specified directory was deleted successfully
1808+ EOF - The specified directory could not be deleted
1809+ Side Effects:
1810+ The FSerrno variable will be changed.
1811+ Description:
1812+ The wFSrmdir function passes a RAM pointer to the path to the
1813+ rmdirhelper function.
1814+ Remarks:
1815+ None.
1816+ **************************************************************************/
1817+
1818+int wFSrmdir (unsigned short int * path, unsigned char rmsubdirs);
1819+#endif
1820+
1821+#endif
1822+
1823+#endif
1824+
1825+#ifdef USERDEFINEDCLOCK
1826+
1827+
1828+/***********************************************************************************************************
1829+ Function:
1830+ int SetClockVars (unsigned int year, unsigned char month, unsigned char day, unsigned char hour, unsigned char minute, unsigned char second)
1831+ Summary:
1832+ Manually set timestamp variables
1833+ Conditions:
1834+ USERDEFINEDCLOCK macro defined in FSconfig.h.
1835+ Input:
1836+ year - The year (1980\-2107)
1837+ month - The month (1\-12)
1838+ day - The day of the month (1\-31)
1839+ hour - The hour (0\-23)
1840+ minute - The minute (0\-59)
1841+ second - The second (0\-59)
1842+ Return Values:
1843+ None
1844+ Side Effects:
1845+ Modifies global timing variables
1846+ Description:
1847+ Lets the user manually set the timing variables. The values passed in will be converted to the format
1848+ used by the FAT timestamps.
1849+ Remarks:
1850+ Call this before creating a file or directory (set create time) and
1851+ before closing a file (set last access time, last modified time)
1852+ ***********************************************************************************************************/
1853+
1854+int SetClockVars (unsigned int year, unsigned char month, unsigned char day, unsigned char hour, unsigned char minute, unsigned char second);
1855+#endif
1856+
1857+
1858+#ifdef ALLOW_FILESEARCH
1859+
1860+/***********************************************************************************
1861+ Function:
1862+ int FindFirst (const char * fileName, unsigned int attr, SearchRec * rec)
1863+ Summary:
1864+ Initial search function for the input Ascii fileName
1865+ Conditions:
1866+ None
1867+ Input:
1868+ fileName - The name to search for
1869+ - Parital string search characters
1870+ - * - Indicates the rest of the filename or extension can vary (e.g. FILE.*)
1871+ - ? - Indicates that one character in a filename can vary (e.g. F?LE.T?T)
1872+ attr - The attributes that a found file may have
1873+ - ATTR_READ_ONLY - File may be read only
1874+ - ATTR_HIDDEN - File may be a hidden file
1875+ - ATTR_SYSTEM - File may be a system file
1876+ - ATTR_VOLUME - Entry may be a volume label
1877+ - ATTR_DIRECTORY - File may be a directory
1878+ - ATTR_ARCHIVE - File may have archive attribute
1879+ - ATTR_MASK - All attributes
1880+ rec - pointer to a structure to put the file information in
1881+ Return Values:
1882+ 0 - File was found
1883+ -1 - No file matching the specified criteria was found
1884+ Side Effects:
1885+ Search criteria from previous FindFirst call on passed SearchRec object
1886+ will be lost. "utf16LFNfound" is overwritten after subsequent FindFirst/FindNext
1887+ operations.It is the responsibility of the application to read the "utf16LFNfound"
1888+ before it is lost.The FSerrno variable will be changed.
1889+ Description:
1890+ The FindFirst function will search for a file based on parameters passed in
1891+ by the user. This function will use the FILEfind function to parse through
1892+ the current working directory searching for entries that match the specified
1893+ parameters. If a file is found, its parameters are copied into the SearchRec
1894+ structure, as are the initial parameters passed in by the user and the position
1895+ of the file entry in the current working directory.If the return value of the
1896+ function is 0 then "utf16LFNfoundLength" indicates whether the file found was
1897+ long file name or short file name(8P3 format). The "utf16LFNfoundLength" is non-zero
1898+ for long file name and is zero for 8P3 format."utf16LFNfound" points to the
1899+ address of long file name if found during the operation.
1900+ Remarks:
1901+ Call FindFirst or FindFirstpgm before calling FindNext
1902+ ***********************************************************************************/
1903+
1904+int FindFirst (const char * fileName, unsigned int attr, SearchRec * rec);
1905+
1906+#ifdef SUPPORT_LFN
1907+/***********************************************************************************
1908+ Function:
1909+ int wFindFirst (const unsigned short int * fileName, unsigned int attr, SearchRec * rec)
1910+ Summary:
1911+ Initial search function for the input UTF16 fileName
1912+ Conditions:
1913+ None
1914+ Input:
1915+ fileName - The name to search for
1916+ - Parital string search characters
1917+ - * - Indicates the rest of the filename or extension can vary (e.g. FILE.*)
1918+ - ? - Indicates that one character in a filename can vary (e.g. F?LE.T?T)
1919+ attr - The attributes that a found file may have
1920+ - ATTR_READ_ONLY - File may be read only
1921+ - ATTR_HIDDEN - File may be a hidden file
1922+ - ATTR_SYSTEM - File may be a system file
1923+ - ATTR_VOLUME - Entry may be a volume label
1924+ - ATTR_DIRECTORY - File may be a directory
1925+ - ATTR_ARCHIVE - File may have archive attribute
1926+ - ATTR_MASK - All attributes
1927+ rec - pointer to a structure to put the file information in
1928+ Return Values:
1929+ 0 - File was found
1930+ -1 - No file matching the specified criteria was found
1931+ Side Effects:
1932+ Search criteria from previous wFindFirst call on passed SearchRec object
1933+ will be lost. "utf16LFNfound" is overwritten after subsequent wFindFirst/FindNext
1934+ operations.It is the responsibility of the application to read the "utf16LFNfound"
1935+ before it is lost.The FSerrno variable will be changed.
1936+ Description:
1937+ The wFindFirst function will search for a file based on parameters passed in
1938+ by the user. This function will use the FILEfind function to parse through
1939+ the current working directory searching for entries that match the specified
1940+ parameters. If a file is found, its parameters are copied into the SearchRec
1941+ structure, as are the initial parameters passed in by the user and the position
1942+ of the file entry in the current working directory.If the return value of the
1943+ function is 0 then "utf16LFNfoundLength" indicates whether the file found was
1944+ long file name or short file name(8P3 format). The "utf16LFNfoundLength" is non-zero
1945+ for long file name and is zero for 8P3 format."utf16LFNfound" points to the
1946+ address of long file name if found during the operation.
1947+ Remarks:
1948+ Call FindFirst or FindFirstpgm before calling FindNext
1949+ ***********************************************************************************/
1950+
1951+int wFindFirst (const unsigned short int * fileName, unsigned int attr, SearchRec * rec);
1952+#endif
1953+
1954+/**********************************************************************
1955+ Function:
1956+ int FindNext (SearchRec * rec)
1957+ Summary:
1958+ Sequential search function
1959+ Conditions:
1960+ None
1961+ Input:
1962+ rec - The structure to store the file information in
1963+ Return Values:
1964+ 0 - File was found
1965+ -1 - No additional files matching the specified criteria were found
1966+ Side Effects:
1967+ Search criteria from previous FindNext call on passed SearchRec object
1968+ will be lost. "utf16LFNfound" is overwritten after subsequent FindFirst/FindNext
1969+ operations.It is the responsibility of the application to read the "utf16LFNfound"
1970+ before it is lost.The FSerrno variable will be changed.
1971+ Description:
1972+ The FindNext function performs the same function as the FindFirst
1973+ funciton, except it does not copy any search parameters into the
1974+ SearchRec structure (only info about found files) and it begins
1975+ searching at the last directory entry offset at which a file was
1976+ found, rather than at the beginning of the current working
1977+ directory.If the return value of the function is 0 then "utf16LFNfoundLength"
1978+ indicates whether the file found was long file name or short file
1979+ name(8P3 format). The "utf16LFNfoundLength" is non-zero for long file name
1980+ and is zero for 8P3 format."utf16LFNfound" points to the address of long
1981+ file name if found during the operation.
1982+ Remarks:
1983+ Call FindFirst or FindFirstpgm before calling this function
1984+ **********************************************************************/
1985+
1986+int FindNext (SearchRec * rec);
1987+#endif
1988+
1989+
1990+/**********************************************************************
1991+ Function:
1992+ // PIC24/30/33/32
1993+ int FSfprintf (FSFILE * fptr, const char * fmt, ...)
1994+ // PIC18
1995+ int FSfpritnf (FSFILE * fptr, const rom char * fmt, ...)
1996+ Summary:
1997+ Function to write formatted strings to a file
1998+ Conditions:
1999+ For PIC18, integer promotion must be enabled in the project build
2000+ options menu. File opened in a write mode.
2001+ Input:
2002+ fptr - A pointer to the file to write to.
2003+ fmt - A string of characters and format specifiers to write to
2004+ the file
2005+ ... - Additional arguments inserted in the string by format
2006+ specifiers
2007+ Returns:
2008+ The number of characters written to the file
2009+ Side Effects:
2010+ The FSerrno variable will be changed.
2011+ Description:
2012+ Writes a specially formatted string to a file.
2013+ Remarks:
2014+ Consult AN1045 for a full description of how to use format
2015+ specifiers.
2016+ **********************************************************************/
2017+
2018+#ifdef ALLOW_FSFPRINTF
2019+ #ifdef __18CXX
2020+ int FSfprintf (FSFILE *fptr, const rom char *fmt, ...);
2021+ #else
2022+ int FSfprintf (FSFILE *fptr, const char * fmt, ...);
2023+ #endif
2024+#endif
2025+
2026+
2027+/**************************************************************************
2028+ Function:
2029+ int FSerror (void)
2030+ Summary:
2031+ Return an error code for the last function call
2032+ Conditions:
2033+ The return value depends on the last function called.
2034+ Input:
2035+ None
2036+ Side Effects:
2037+ None.
2038+ Return Values:
2039+ FSInit -
2040+ - CE_GOOD ・ No Error
2041+ - CE_INIT_ERROR ・ The physical media could not be initialized
2042+ - CE_BAD_SECTOR_READ ・ The MBR or the boot sector could not be
2043+ read correctly
2044+ - CE_BAD_PARITION ・ The MBR signature code was incorrect.
2045+ - CE_NOT_FORMATTED ・ The boot sector signature code was incorrect or
2046+ indicates an invalid number of bytes per sector.
2047+ - CE_CARDFAT32 ・ The physical media is FAT32 type (only an error
2048+ when FAT32 support is disabled).
2049+ - CE_UNSUPPORTED_FS ・ The device is formatted with an unsupported file
2050+ system (not FAT12 or 16).
2051+ FSfopen -
2052+ - CE_GOOD ・ No Error
2053+ - CE_NOT_INIT ・ The device has not been initialized.
2054+ - CE_TOO_MANY_FILES_OPEN ・ The function could not allocate any
2055+ additional file information to the array
2056+ of FSFILE structures or the heap.
2057+ - CE_INVALID_FILENAME ・ The file name argument was invalid.
2058+ - CE_INVALID_ARGUMENT ・ The user attempted to open a directory in a
2059+ write mode or specified an invalid mode argument.
2060+ - CE_FILE_NOT_FOUND ・ The specified file (which was to be opened in read
2061+ mode) does not exist on the device.
2062+ - CE_BADCACHEREAD ・ A read from the device failed.
2063+ - CE_ERASE_FAIL ・ The existing file could not be erased (when opening
2064+ a file in WRITE mode).
2065+ - CE_DIR_FULL ・ The directory is full.
2066+ - CE_DISK_FULL・ The data memory section is full.
2067+ - CE_WRITE_ERROR ・ A write to the device failed.
2068+ - CE_SEEK_ERROR ・ The current position in the file could not be set to
2069+ the end (when the file was opened in APPEND mode).
2070+ FSfclose -
2071+ - CE_GOOD ・ No Error
2072+ - CE_WRITE_ERROR ・ The existing data in the data buffer or the new file
2073+ entry information could not be written to the device.
2074+ - CE_BADCACHEREAD ・ The file entry information could not be cached
2075+ FSfread -
2076+ - CE_GOOD ・ No Error
2077+ - CE_WRITEONLY ・ The file was opened in a write-only mode.
2078+ - CE_WRITE_ERROR ・ The existing data in the data buffer could not be
2079+ written to the device.
2080+ - CE_BAD_SECTOR_READ ・ The data sector could not be read.
2081+ - CE_EOF ・ The end of the file was reached.
2082+ - CE_COULD_NOT_GET_CLUSTER ・Additional clusters in the file could not be loaded.
2083+ FSfwrite -
2084+ - CE_GOOD ・ No Error
2085+ - CE_READONLY ・ The file was opened in a read-only mode.
2086+ - CE_WRITE_PROTECTED ・ The device write-protect check function indicated
2087+ that the device has been write-protected.
2088+ - CE_WRITE_ERROR ・ There was an error writing data to the device.
2089+ - CE_BADCACHEREAD ・ The data sector to be modified could not be read from
2090+ the device.
2091+ - CE_DISK_FULL ・ All data clusters on the device are in use.
2092+ FSfseek -
2093+ - CE_GOOD ・ No Error
2094+ - CE_WRITE_ERROR ・ The existing data in the data buffer could not be
2095+ written to the device.
2096+ - CE_INVALID_ARGUMENT ・ The specified offset exceeds the size of the file.
2097+ - CE_BADCACHEREAD ・ The sector that contains the new current position
2098+ could not be loaded.
2099+ - CE_COULD_NOT_GET_CLUSTER ・Additional clusters in the file could not be
2100+ loaded/allocated.
2101+ FSftell -
2102+ - CE_GOOD ・ No Error
2103+ FSattrib -
2104+ - CE_GOOD ・ No Error
2105+ - CE_INVALID_ARGUMENT ・ The attribute argument was invalid.
2106+ - CE_BADCACHEREAD ・ The existing file entry information could not be
2107+ loaded.
2108+ - CE_WRITE_ERROR ・ The file entry information could not be written to
2109+ the device.
2110+ FSrename -
2111+ - CE_GOOD ・ No Error
2112+ - CE_FILENOTOPENED ・ A null file pointer was passed into the function.
2113+ - CE_INVALID_FILENAME ・ The file name passed into the function was invalid.
2114+ - CE_BADCACHEREAD ・ A read from the device failed.
2115+ - CE_FILENAME_EXISTS ・ A file with the specified name already exists.
2116+ - CE_WRITE_ERROR ・ The new file entry data could not be written to the
2117+ device.
2118+ FSfeof -
2119+ - CE_GOOD ・ No Error
2120+ FSformat -
2121+ - CE_GOOD ・ No Error
2122+ - CE_INIT_ERROR ・ The device could not be initialized.
2123+ - CE_BADCACHEREAD ・ The master boot record or boot sector could not be
2124+ loaded successfully.
2125+ - CE_INVALID_ARGUMENT ・ The user selected to create their own boot sector on
2126+ a device that has no master boot record, or the mode
2127+ argument was invalid.
2128+ - CE_WRITE_ERROR ・ The updated MBR/Boot sector could not be written to
2129+ the device.
2130+ - CE_BAD_PARTITION ・ The calculated number of sectors per clusters was
2131+ invalid.
2132+ - CE_NONSUPPORTED_SIZE ・ The card has too many sectors to be formatted as
2133+ FAT12 or FAT16.
2134+ FSremove -
2135+ - CE_GOOD ・ No Error
2136+ - CE_WRITE_PROTECTED ・ The device write-protect check function indicated
2137+ that the device has been write-protected.
2138+ - CE_INVALID_FILENAME ・ The specified filename was invalid.
2139+ - CE_FILE_NOT_FOUND ・ The specified file could not be found.
2140+ - CE_ERASE_FAIL ・ The file could not be erased.
2141+ FSchdir -
2142+ - CE_GOOD ・ No Error
2143+ - CE_INVALID_ARGUMENT ・ The path string was mis-formed or the user tried to
2144+ change to a non-directory file.
2145+ - CE_BADCACHEREAD ・ A directory entry could not be cached.
2146+ - CE_DIR_NOT_FOUND ・ Could not find a directory in the path.
2147+ FSgetcwd -
2148+ - CE_GOOD ・ No Error
2149+ - CE_INVALID_ARGUMENT ・ The user passed a 0-length buffer into the function.
2150+ - CE_BADCACHEREAD ・ A directory entry could not be cached.
2151+ - CE_BAD_SECTOR_READ ・ The function could not determine a previous directory
2152+ of the current working directory.
2153+ FSmkdir -
2154+ - CE_GOOD ・ No Error
2155+ - CE_WRITE_PROTECTED ・ The device write-protect check function indicated
2156+ that the device has been write-protected.
2157+ - CE_INVALID_ARGUMENT ・ The path string was mis-formed.
2158+ - CE_BADCACHEREAD ・ Could not successfully change to a recently created
2159+ directory to store its dir entry information, or
2160+ could not cache directory entry information.
2161+ - CE_INVALID_FILENAME ・ One or more of the directory names has an invalid
2162+ format.
2163+ - CE_WRITE_ERROR ・ The existing data in the data buffer could not be
2164+ written to the device or the dot/dotdot entries could
2165+ not be written to a newly created directory.
2166+ - CE_DIR_FULL ・ There are no available dir entries in the CWD.
2167+ - CE_DISK_FULL ・ There are no available clusters in the data region of
2168+ the device.
2169+ FSrmdir -
2170+ - CE_GOOD ・ No Error
2171+ - CE_DIR_NOT_FOUND ・ The directory specified could not be found or the
2172+ function could not change to a subdirectory within
2173+ the directory to be deleted (when recursive delete is
2174+ enabled).
2175+ - CE_INVALID_ARGUMENT ・ The user tried to remove the CWD or root directory.
2176+ - CE_BADCACHEREAD ・ A directory entry could not be cached.
2177+ - CE_DIR_NOT_EMPTY ・ The directory to be deleted was not empty and
2178+ recursive subdirectory removal was disabled.
2179+ - CE_ERASE_FAIL ・ The directory or one of the directories or files
2180+ within it could not be deleted.
2181+ - CE_BAD_SECTOR_READ ・ The function could not determine a previous directory
2182+ of the CWD.
2183+ SetClockVars -
2184+ - CE_GOOD ・ No Error
2185+ - CE_INVALID_ARGUMENT ・ The time values passed into the function were
2186+ invalid.
2187+ FindFirst -
2188+ - CE_GOOD ・ No Error
2189+ - CE_INVALID_FILENAME ・ The specified filename was invalid.
2190+ - CE_FILE_NOT_FOUND ・ No file matching the specified criteria was found.
2191+ - CE_BADCACHEREAD ・ The file information for the file that was found
2192+ could not be cached.
2193+ FindNext -
2194+ - CE_GOOD ・ No Error
2195+ - CE_NOT_INIT ・ The SearchRec object was not initialized by a call to
2196+ FindFirst.
2197+ - CE_INVALID_ARGUMENT ・ The SearchRec object was initialized in a different
2198+ directory from the CWD.
2199+ - CE_INVALID_FILENAME ・ The filename is invalid.
2200+ - CE_FILE_NOT_FOUND ・ No file matching the specified criteria was found.
2201+ FSfprintf -
2202+ - CE_GOOD ・ No Error
2203+ - CE_WRITE_ERROR ・ Characters could not be written to the file.
2204+ Description:
2205+ The FSerror function will return the FSerrno variable. This global
2206+ variable will have been set to an error value during the last call of a
2207+ library function.
2208+ Remarks:
2209+ None
2210+ **************************************************************************/
2211+
2212+int FSerror (void);
2213+
2214+
2215+/*********************************************************************************
2216+ Function:
2217+ int FSCreateMBR (unsigned long firstSector, unsigned long numSectors)
2218+ Summary:
2219+ Creates a master boot record
2220+ Conditions:
2221+ The I/O pins for the device have been initialized by the InitIO function.
2222+ Input:
2223+ firstSector - The first sector of the partition on the device (cannot
2224+ be 0; that's the MBR)
2225+ numSectors - The number of sectors available in memory (including the
2226+ MBR)
2227+ Return Values:
2228+ 0 - MBR was created successfully
2229+ EOF - MBR could not be created
2230+ Side Effects:
2231+ None
2232+ Description:
2233+ This function can be used to create a master boot record for a device. Note
2234+ that this function should not be used on a device that is already formatted
2235+ with a master boot record (i.e. most SD cards, CF cards, USB keys). This
2236+ function will fill the global data buffer with appropriate partition information
2237+ for a FAT partition with a type determined by the number of sectors available
2238+ to the partition. It will then write the MBR information to the first sector
2239+ on the device. This function should be followed by a call to FSformat, which
2240+ will create a boot sector, root dir, and FAT appropriate the the information
2241+ contained in the new master boot record. Note that FSformat only supports
2242+ FAT12 and FAT16 formatting at this time, and so cannot be used to format a
2243+ device with more than 0x3FFD5F sectors.
2244+ Remarks:
2245+ This function can damage the device being used, and should not be called
2246+ unless the user is sure about the size of the device and the first sector value.
2247+ *********************************************************************************/
2248+
2249+int FSCreateMBR (unsigned long firstSector, unsigned long numSectors);
2250+
2251+
2252+#ifdef ALLOW_GET_DISK_PROPERTIES
2253+/*********************************************************************************
2254+ Function:
2255+ void FSGetDiskProperties(FS_DISK_PROPERTIES* properties)
2256+ Summary:
2257+ Allows user to get the disk properties (size of disk, free space, etc)
2258+ Conditions:
2259+ 1) ALLOW_GET_DISK_PROPERTIES must be defined in FSconfig.h
2260+ 2) a FS_DISK_PROPERTIES object must be created before the function is called
2261+ 3) the new_request member of the FS_DISK_PROPERTIES object must be set before
2262+ calling the function for the first time. This will start a new search.
2263+ 4) this function should not be called while there is a file open. Close all
2264+ files before calling this function.
2265+ Input:
2266+ properties - a pointer to a FS_DISK_PROPERTIES object where the results should
2267+ be stored.
2268+ Return Values:
2269+ This function returns void. The properties_status of the previous call of
2270+ this function is located in the properties.status field. This field has
2271+ the following possible values:
2272+
2273+ FS_GET_PROPERTIES_NO_ERRORS - operation completed without error. Results
2274+ are in the properties object passed into the function.
2275+ FS_GET_PROPERTIES_DISK_NOT_MOUNTED - there is no mounted disk. Results in
2276+ properties object is not valid
2277+ FS_GET_PROPERTIES_CLUSTER_FAILURE - there was a failure trying to read a
2278+ cluster from the drive. The results in the properties object is a partial
2279+ result up until the point of the failure.
2280+ FS_GET_PROPERTIES_STILL_WORKING - the search for free sectors is still in
2281+ process. Continue calling this function with the same properties pointer
2282+ until either the function completes or until the partial results meets the
2283+ application needs. The properties object contains the partial results of
2284+ the search and can be used by the application.
2285+ Side Effects:
2286+ Can cause errors if called when files are open. Close all files before
2287+ calling this function.
2288+
2289+ Calling this function without setting the new_request member on the first
2290+ call can result in undefined behavior and results.
2291+
2292+ Calling this function after a result is returned other than
2293+ FS_GET_PROPERTIES_STILL_WORKING can result in undefined behavior and results.
2294+ Description:
2295+ This function returns the information about the mounted drive. The results
2296+ member of the properties object passed into the function is populated with
2297+ the information about the drive.
2298+
2299+ Before starting a new request, the new_request member of the properties
2300+ input parameter should be set to TRUE. This will initiate a new search
2301+ request.
2302+
2303+ This function will return before the search is complete with partial results.
2304+ All of the results except the free_clusters will be correct after the first
2305+ call. The free_clusters will contain the number of free clusters found up
2306+ until that point, thus the free_clusters result will continue to grow until
2307+ the entire drive is searched. If an application only needs to know that a
2308+ certain number of bytes is available and doesn't need to know the total free
2309+ size, then this function can be called until the required free size is
2310+ verified. To continue a search, pass a pointer to the same FS_DISK_PROPERTIES
2311+ object that was passed in to create the search.
2312+
2313+ A new search request sould be made once this function has returned a value
2314+ other than FS_GET_PROPERTIES_STILL_WORKING. Continuing a completed search
2315+ can result in undefined behavior or results.
2316+
2317+ Typical Usage:
2318+ <code>
2319+ FS_DISK_PROPERTIES disk_properties;
2320+
2321+ disk_properties.new_request = TRUE;
2322+
2323+ do
2324+ {
2325+ FSGetDiskProperties(&disk_properties);
2326+ } while (disk_properties.properties_status == FS_GET_PROPERTIES_STILL_WORKING);
2327+ </code>
2328+
2329+ results.disk_format - contains the format of the drive. Valid results are
2330+ FAT12(1), FAT16(2), or FAT32(3).
2331+
2332+ results.sector_size - the sector size of the mounted drive. Valid values are
2333+ 512, 1024, 2048, and 4096.
2334+
2335+ results.sectors_per_cluster - the number sectors per cluster.
2336+
2337+ results.total_clusters - the number of total clusters on the drive. This
2338+ can be used to calculate the total disk size (total_clusters *
2339+ sectors_per_cluster * sector_size = total size of drive in bytes)
2340+
2341+ results.free_clusters - the number of free (unallocated) clusters on the drive.
2342+ This can be used to calculate the total free disk size (free_clusters *
2343+ sectors_per_cluster * sector_size = total size of drive in bytes)
2344+
2345+ Remarks:
2346+ PIC24F size estimates:
2347+ Flash - 400 bytes (-Os setting)
2348+
2349+ PIC24F speed estimates:
2350+ Search takes approximately 7 seconds per Gigabyte of drive space. Speed
2351+ will vary based on the number of sectors per cluster and the sector size.
2352+ *********************************************************************************/
2353+void FSGetDiskProperties(FS_DISK_PROPERTIES* properties);
2354+#endif
2355+
2356+
2357+#endif
--- mips/tags/megalopa1.0/envspecific.c (revision 0)
+++ 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/exception.c (revision 0)
+++ mips/tags/megalopa1.0/exception.c (revision 270)
@@ -0,0 +1,159 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by K.Tanaka & Katsumi
4+ http://www.ze.em-net.ne.jp/~kenken/index.html
5+ http://hp.vector.co.jp/authors/VA016157/
6+*/
7+
8+#include <xc.h>
9+#include "api.h"
10+#include "main.h"
11+#include "compiler.h"
12+
13+/*
14+ Enable following line if memory dump is needed when exception occurs.
15+*/
16+
17+//#define DUMPFILE "~~MEMORY.DMP"
18+
19+#ifdef DUMPFILE
20+void dumpMemory(){
21+ unsigned int i;
22+ FSFILE *fp;
23+ printstr("\n"DUMPFILE" ");
24+ if(FSInit()==FALSE){
25+ printstr("cannot be created.\n");
26+ return;
27+ }
28+ fp=FSfopen(DUMPFILE,"w");
29+ if(fp==NULL) {
30+ printstr("not saved.\n");
31+ return;
32+ }
33+ for(i=0;i<PERSISTENT_RAM_SIZE;i+=512){
34+ if (FSfwrite(&RAM[i],1,512,fp)<512) break;
35+ }
36+ FSfclose(fp);
37+ printstr("saved.\n");
38+}
39+#else
40+void dumpMemory(){}
41+#endif //ifdef DUMPFILE
42+
43+void _general_exception_handler (void){
44+ int i;
45+ // $v1 is g_ex_data
46+ asm volatile("la $v1,%0"::"i"(&g_ex_data[0]));
47+ // Prepare proper stack area before SoftReset
48+ asm volatile("addiu $sp,$v1,0xfff0");
49+ // g_ex_data[2]=$s6
50+ asm volatile("sw $s6,8($v1)");
51+ // g_ex_data[3]=Cause
52+ asm volatile("mfc0 $v0,$13");
53+ asm volatile("sw $v0,12($v1)");
54+ // g_ex_data[4]=EPC
55+ asm volatile("mfc0 $v0,$14");
56+ asm volatile("sw $v0,16($v1)");
57+ // Exception occured
58+ g_ex_data[0]=1;
59+ // g_s6
60+ g_ex_data[1]=g_s6;
61+ // Clear 2 MLB bits of EPC
62+ g_ex_data[4]&=0xfffffffc;
63+ // If EPC is within RAM, store data in exception area.
64+ if ((int)(&RAM[0])<=g_ex_data[4] && g_ex_data[4] <(int)(&RAM[RAMSIZE])) {
65+ // g_ex_data[5] - g_ex_data[12]: assembly
66+ for(i=-3;i<=3;i++){
67+ g_ex_data[i+8]=((int*)g_ex_data[4])[i];
68+ }
69+ }
70+ // Wait until all buttons are released and reset MachiKania.
71+ #ifdef __DEBUG
72+ asm volatile("j 0xBFC00000");
73+ #else
74+ for(i=0;i<100000;i++){
75+ if((readbuttons()&(KEYUP|KEYDOWN|KEYLEFT|KEYRIGHT|KEYSTART|KEYFIRE))
76+ !=(KEYUP|KEYDOWN|KEYLEFT|KEYRIGHT|KEYSTART|KEYFIRE)) i=0;
77+ }
78+ asm volatile("j SoftReset");
79+ #endif
80+}
81+
82+void blue_screen(void){
83+ int i,j,s6,s6g;
84+ unsigned int* opos;
85+ if (RCONbits.POR || RCONbits.EXTR) {
86+ // After power on or reset. Reset flags and return.
87+ RCONbits.POR=0;
88+ RCONbits.EXTR=0;
89+ for(i=0;i<RAMSIZE;i++){
90+ // Reset all RAM area including g_ex_data[]
91+ RAM[i]=0;
92+ }
93+ return;
94+ } else if (g_ex_data[0]==0) {
95+ // No exception found.
96+ return;
97+ }
98+ // Exception occured before SoftReset().
99+ // Prepare data
100+ s6=g_ex_data[2];
101+ s6g=g_ex_data[1];
102+ s6=s6&0x7fffffff;
103+ s6g=s6g&0x7fffffff;
104+ opos=(int*)g_ex_data[4];
105+ //set_bgcolor(255,0,0);
106+ printstr("STOP");
107+ printstr("\nException at ");
108+ printhex32(g_ex_data[4]);
109+ printstr("\n Cause: ");
110+ printhex32(g_ex_data[3]);
111+ printstr("\n ");
112+ switch((g_ex_data[3]>>2)&0x1f){
113+ case 0: printstr("(Interrupt)"); break;
114+ case 1: printstr("(TLB modification)"); break;
115+ case 2: printstr("(TLB load/fetch)"); break;
116+ case 3: printstr("(TLB store)"); break;
117+ case 4: printstr("(Address load/fetch error )"); break;
118+ case 5: printstr("(Address store error)"); break;
119+ case 6: printstr("(Bus fetch error)"); break;
120+ case 7: printstr("(Bus load/store error)"); break;
121+ case 8: printstr("(Syscall)"); break;
122+ case 9: printstr("(Breakpoint)"); break;
123+ case 10: printstr("(Reserved instruction)"); break;
124+ case 11: printstr("(Coprocessor Unusable)"); break;
125+ case 12: printstr("(Integer Overflow)"); break;
126+ case 13: printstr("(Trap)"); break;
127+ case 23: printstr("(Reference to Watch address)"); break;
128+ case 24: printstr("(Machine check)"); break;
129+ default: printstr("(Unknown)"); break;
130+ }
131+ printstr("\n s6: ");
132+ printstr(resolve_label(s6));
133+ printstr("\n g_s6: ");
134+ printstr(resolve_label(s6g));
135+ printstr("\n");
136+ printstr("Reset MachiKania to contine.\n\n");
137+ // Show code where the exception happened.
138+ for(i=-3;i<=3;i++){
139+ printstr("\n ");
140+ printhex32((unsigned int)&opos[i]);
141+ printstr(" ");
142+ if ((unsigned int)&RAM[0]<=(unsigned int)&opos[i] && (unsigned int)&opos[i]<(unsigned int)&RAM[RAMSIZE]) {
143+ // Exception in RAM[RAMSIZE] area
144+ printhex32(g_ex_data[i+8]);
145+ } else if ( 0xA0000000<=(unsigned int)&opos[i] && (unsigned int)&opos[i]<0xA0000000+PIC32MX_RAMSIZE
146+ || 0x9D000000<=(unsigned int)&opos[i] && (unsigned int)&opos[i]<=0x9D000000+PIC32MX_FLASHSIZE) {
147+ // Exception in outside RAM[RAMSIZE] or flash area
148+ printhex32(opos[i]);
149+ } else {
150+ printstr("********");
151+ }
152+ }
153+ printstr("\n");
154+
155+#ifndef __DEBUG
156+ dumpMemory();
157+#endif
158+ while(1) asm("wait");
159+}
--- mips/tags/megalopa1.0/envspecific.h (revision 0)
+++ mips/tags/megalopa1.0/envspecific.h (revision 270)
@@ -0,0 +1,90 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by Katsumi.
4+ http://hp.vector.co.jp/authors/VA016157/
5+ kmorimatsu@users.sourceforge.jp
6+*/
7+
8+// Megalopa uses I/O statements/functions
9+#include "io.h"
10+
11+#define PERSISTENT_RAM_SIZE (1024*100)
12+
13+int readbuttons();
14+void scroll(int x, int y);
15+void usegraphic(int mode);
16+void videowidth(int width);
17+int lib_system(int a0, int a1 ,int v0, int a3, int g_gcolor, int g_prev_x, int g_prev_y);
18+void init_env(void);
19+void pre_run(void);
20+void post_run(void);
21+
22+// 30 or 40 characters per line for Zoea
23+#define printcomma() printstr(" "+rem10_32((unsigned int)(cursor-TVRAM)))
24+
25+// Check break key or buttons when executing BASIC code.
26+// In PS/2 mode, detect ctrl-break.
27+// In button mode, detect pushing four buttons are pushed simultaneously.
28+#define check_break() \
29+ if (g_disable_break==0) {\
30+ if (ps2keystatus[0x03]) err_break();\
31+ }
32+
33+// Megalopa specific lists of statements and functions
34+#define ADDITIONAL_STATEMENTS \
35+ "OUT " ,out_statement,\
36+ "OUT8H " ,out8h_statement,\
37+ "OUT8L " ,out8l_statement,\
38+ "OUT16 " ,out16_statement,\
39+ "PWM " ,pwm_statement,\
40+ "SERIAL " ,serial_statement,\
41+ "SERIALOUT ",serialout_statement,
42+
43+#define ADDITIONAL_INT_FUNCTIONS \
44+ "IN(" , in_function,\
45+ "IN8H(" , in8h_function,\
46+ "IN8L(" , in8l_function,\
47+ "IN16(" , in16_function,\
48+ "ANALOG(" ,analog_function,\
49+ "SERIALIN(",serialin_function,
50+
51+#define ADDITIONAL_STR_FUNCTIONS
52+#define ADDITIONAL_RESERVED_VAR_NAMES \
53+ 0x00015045, /*OUT*/ \
54+ 0x01975e81, /*OUT8H*/ \
55+ 0x01975e85, /*OUT8L*/ \
56+ 0x01975d7a, /*OUT16*/ \
57+ 0x0001015b, /*IN*/ \
58+ 0x0007dde1, /*IN8H*/ \
59+ 0x0007dde5, /*IN8L*/ \
60+ 0x0007dcda, /*IN16*/ \
61+ 0x05f0a740, /*ANALOG*/ \
62+ 0x00015596, /*PWM*/ \
63+ 0x45f58f5d, /*SERIAL*/ \
64+ 0x000163c6, /*SPI*/ \
65+ 0x47093355, /*SPIOUT*/ \
66+ 0x01fa1cff, /*SPIIN*/
67+
68+
69+#define EXTRA_MASK 0x003F
70+#define EXTRA_STEP 0x0001
71+enum extra{
72+ EXTRA_SYSTEM =EXTRA_STEP*0,
73+ EXTRA_OUT =EXTRA_STEP*1,
74+ EXTRA_OUT8H =EXTRA_STEP*2,
75+ EXTRA_OUT8L =EXTRA_STEP*3,
76+ EXTRA_OUT16 =EXTRA_STEP*4,
77+ EXTRA_IN =EXTRA_STEP*5,
78+ EXTRA_IN8H =EXTRA_STEP*6,
79+ EXTRA_IN8L =EXTRA_STEP*7,
80+ EXTRA_IN16 =EXTRA_STEP*8,
81+ EXTRA_ANALOG =EXTRA_STEP*9,
82+ EXTRA_PWM =EXTRA_STEP*10,
83+ EXTRA_SERIALOUT =EXTRA_STEP*11,
84+ EXTRA_SERIALIN =EXTRA_STEP*12,
85+ EXTRA_SERIAL =EXTRA_STEP*13,
86+ EXTRA_SPIOUT =EXTRA_STEP*14,
87+ EXTRA_SPIIN =EXTRA_STEP*15,
88+ EXTRA_SPI =EXTRA_STEP*16,
89+ // MAX 63
90+};
--- mips/tags/megalopa1.0/library.c (revision 0)
+++ 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+