BASIC compiler/interpreter for PIC32MX/MZ-80K
修訂 | 3beac033cf70cabacfb722bcde919574506edb13 (tree) |
---|---|
時間 | 2019-05-26 11:28:20 |
作者 | Katsumi <kmorimatsu@sour...> |
Commiter | Katsumi |
Debug: Exception when using CLIB in MSRA
@@ -112,11 +112,14 @@ const void* const g_data_clib[]={ | ||
112 | 112 | // CLIB name used (name as 31 bit integer) |
113 | 113 | static unsigned int g_clib; |
114 | 114 | |
115 | +void init_clib(){ | |
116 | + // Initialize g_data_clib_var[] | |
117 | + g_data_clib_var[0]=(void*)g_gp; | |
118 | +} | |
119 | + | |
115 | 120 | char* useclib_statement(){ |
116 | 121 | int i; |
117 | 122 | int* cmpdata; |
118 | - // Initialize g_data_clib_var[] | |
119 | - g_data_clib_var[0]=(void*)g_gp; | |
120 | 123 | do { |
121 | 124 | next_position(); |
122 | 125 | i=check_var_name(); |
@@ -266,7 +269,9 @@ char* clib_main(){ | ||
266 | 269 | g_object[g_objpos++]=0x3C050000|((((unsigned int)(0xA0008000+adjust))>>16)&0x0000FFFF); // lui a1,xxxx |
267 | 270 | g_object[g_objpos++]=0x34A50000|(((unsigned int)(0xA0008000+adjust))&0x0000FFFF); // ori a1,a1,xxxx |
268 | 271 | call_quicklib_code(call_clib_init,ASM_ADDIU_A0_ZERO_ | 0); |
269 | - // All done | |
272 | + // All done. Shift g_object as the beginning of main BASIC code. | |
273 | + g_object+=g_objpos; | |
274 | + g_objpos=0; | |
270 | 275 | return 0; |
271 | 276 | } |
272 | 277 |
@@ -398,6 +398,7 @@ char* coretimer_statement(); | ||
398 | 398 | char* coretimer_function(); |
399 | 399 | char* interrupt_statement(); |
400 | 400 | |
401 | +void init_clib(); | |
401 | 402 | char* useclib_statement(); |
402 | 403 | char* useclib_begin(char* buff); |
403 | 404 | char* clib_method(char type); |
@@ -89,6 +89,8 @@ char* compile_file(){ | ||
89 | 89 | char* err; |
90 | 90 | // Read first 512 bytes |
91 | 91 | read_file(512); |
92 | + // Skip BOM (UTF-8) if exists | |
93 | + if (0xEF==g_source[0] && 0xBB==g_source[1] && 0xBF==g_source[2]) g_srcpos=3; | |
92 | 94 | // Compile line by line |
93 | 95 | while (g_size==512) { |
94 | 96 | err=compile_line(); |
@@ -46,7 +46,7 @@ int runbasic(char *appname,int mode){ | ||
46 | 46 | // -1:ファイルエラー |
47 | 47 | // -2:リンクエラー |
48 | 48 | // 1以上:コンパイルエラーの発生行(行番号ではなくファイル上の何行目か) |
49 | - int i; | |
49 | + int i,j; | |
50 | 50 | char* buff; |
51 | 51 | char* err; |
52 | 52 |
@@ -85,19 +85,23 @@ int runbasic(char *appname,int mode){ | ||
85 | 85 | // Initialize music system |
86 | 86 | init_music(); |
87 | 87 | |
88 | + // Initialize clib | |
89 | + init_clib(); | |
90 | + | |
88 | 91 | printstr("BASIC "BASVER"\n"); |
89 | 92 | wait60thsec(15); |
90 | 93 | |
91 | 94 | printstr("Compiling..."); |
92 | 95 | |
93 | 96 | if (mode==RUNMODE_COPY_AND_RUN) { |
94 | - // Copy the object from MOS | |
95 | - appname=(char*)MACHIKANIA_OBJ_ADDRESS; | |
96 | - for(i=0;i<RAMSIZE;i++) RAM[i]=appname[i]; | |
97 | 97 | // Set g_object/g_objpos for library functions like lib_read(). |
98 | 98 | // The g_object/g_objpos values are stoared just before MOS. |
99 | 99 | g_object=(int*)g_object_mos; |
100 | 100 | g_objpos=g_objpos_mos; |
101 | + // Copy the object from MOS | |
102 | + j=(int)(&g_object[g_objpos])-(int)(&RAM[0]); | |
103 | + appname=(char*)MACHIKANIA_OBJ_ADDRESS; | |
104 | + for(i=0;i<j;i++) RAM[i]=appname[i]; | |
101 | 105 | } else { |
102 | 106 | // Initialize compiler |
103 | 107 | cmpdata_init(); |
@@ -0,0 +1,431 @@ | ||
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 | +/* | |
9 | + This file is shared by Megalopa and Zoea | |
10 | +*/ | |
11 | + | |
12 | +#include "compiler.h" | |
13 | +#include "api.h" | |
14 | +#include "main.h" | |
15 | + | |
16 | +/* | |
17 | + CMPDATA_USECLIB structure | |
18 | + type: CMPDATA_USECLIB (8) | |
19 | + len: 2 | |
20 | + data16: n/a (0) | |
21 | + record[1]: clib name as integer | |
22 | + | |
23 | + CMPDATA_CLIBFUNC structure | |
24 | + type: CMPDATA_CLIBFUNC (9) | |
25 | + len: 4 | |
26 | + data16: n/a (0) | |
27 | + record[1]: clib name as integer | |
28 | + record[2]: func name as integer | |
29 | + record[3]: pointer to function | |
30 | +*/ | |
31 | + | |
32 | +/* | |
33 | + * g_data_clib[] contains the data from MachiKania compiler for this library | |
34 | + */ | |
35 | +void* g_data_clib_var[]={ | |
36 | + 0, // will be g_gp, g_data[0][0],"0" | |
37 | +}; | |
38 | + | |
39 | +const void* const g_data_clib_core[]={ | |
40 | + lib_calloc_memory,// g_data[1][0],"0" | |
41 | + lib_delete, // g_data[1][1],"4" | |
42 | +}; | |
43 | + | |
44 | +const void* const g_data_clib_file[]={ | |
45 | +#ifdef __DEBUG | |
46 | + 0 // Disabled in debug mode | |
47 | +#else | |
48 | + FSInit, // g_data[2][0],"0" | |
49 | + FSfopen, // g_data[2][1],"4" | |
50 | + FSfclose, // g_data[2][2],"8" | |
51 | + FSfread, // g_data[2][3],"12" | |
52 | + FSfwrite, // g_data[2][4],"16" | |
53 | + FSfeof, // g_data[2][5],"20" | |
54 | + FSftell, // g_data[2][6],"24" | |
55 | + FSfseek, // g_data[2][7],"28" | |
56 | + FSrewind, // g_data[2][8],"32" | |
57 | + FindFirst,// g_data[2][9],"36" | |
58 | + FindNext, // g_data[2][10],"40" | |
59 | + FSmkdir, // g_data[2][11],"44" | |
60 | + FSgetcwd, // g_data[2][12],"48" | |
61 | + FSchdir, // g_data[2][13],"52" | |
62 | + FSremove, // g_data[2][14],"56" | |
63 | + FSrename, // g_data[2][15],"60" | |
64 | +#endif | |
65 | +}; | |
66 | + | |
67 | +const void* const g_data_clib_video[]={ | |
68 | + start_composite,// g_data[3][0],"0" | |
69 | + stop_composite, // g_data[3][1],"4" | |
70 | + printchar, // g_data[3][2],"8" | |
71 | + printstr, // g_data[3][3],"12" | |
72 | + printnum, // g_data[3][4],"16" | |
73 | + printnum2, // g_data[3][5],"20" | |
74 | + cls, // g_data[3][6],"24" | |
75 | + vramscroll, // g_data[3][7],"28" | |
76 | + setcursorcolor, // g_data[3][8],"32" | |
77 | + setcursor, // g_data[3][9],"36" | |
78 | + set_palette, // g_data[3][10],"40" | |
79 | + set_bgcolor, // g_data[3][11],"44" | |
80 | +}; | |
81 | + | |
82 | +const void* const g_data_clib_graphic[]={ | |
83 | + g_pset, // g_data[4][0],"0" | |
84 | + g_putbmpmn, // g_data[4][1],"4" | |
85 | + g_clrbmpmn, // g_data[4][2],"8" | |
86 | + g_gline, // g_data[4][3],"12" | |
87 | + g_hline, // g_data[4][4],"16" | |
88 | + g_circle, // g_data[4][5],"20" | |
89 | + g_circlefill, // g_data[4][6],"24" | |
90 | + g_boxfill, // g_data[4][7],"28" | |
91 | + g_putfont, // g_data[4][8],"32" | |
92 | + g_printstr, // g_data[4][9],"36" | |
93 | + g_printnum, // g_data[4][10],"40" | |
94 | + g_printnum2, // g_data[4][11],"44" | |
95 | + g_color, // g_data[4][12],"48" | |
96 | +}; | |
97 | + | |
98 | +const void* const g_data_clib_keyboard[]={ | |
99 | + shiftkeys, // g_data[5][0],"0" | |
100 | + ps2readkey,// g_data[5][1],"4" | |
101 | +}; | |
102 | + | |
103 | +const void* const g_data_clib[]={ | |
104 | + &g_data_clib_var[0], // g_data[0],"0" | |
105 | + &g_data_clib_core[0], // g_data[1],"4" | |
106 | + &g_data_clib_file[0], // g_data[2],"8" | |
107 | + &g_data_clib_video[0], // g_data[3],"12" | |
108 | + &g_data_clib_graphic[0], // g_data[4],"16" | |
109 | + &g_data_clib_keyboard[0],// g_data[5],"20" | |
110 | +}; | |
111 | + | |
112 | +// CLIB name used (name as 31 bit integer) | |
113 | +static unsigned int g_clib; | |
114 | + | |
115 | +void init_clib(){ | |
116 | + // Initialize g_data_clib_var[] | |
117 | + g_data_clib_var[0]=(void*)g_gp; | |
118 | +} | |
119 | + | |
120 | +char* useclib_statement(){ | |
121 | + int i; | |
122 | + int* cmpdata; | |
123 | + do { | |
124 | + next_position(); | |
125 | + i=check_var_name(); | |
126 | + if (i<65536) return ERR_SYNTAX; | |
127 | + // Check if the clib already exists | |
128 | + cmpdata_reset(); | |
129 | + while(cmpdata=cmpdata_find(CMPDATA_USECLIB)){ | |
130 | + if (cmpdata[1]==i) { | |
131 | + // The clib was already defined. | |
132 | + i=0; | |
133 | + break; | |
134 | + } | |
135 | + } | |
136 | + if (i) { | |
137 | + // Load new file to define clib. | |
138 | + g_clib=i; | |
139 | + return ERR_COMPILE_CLIB; | |
140 | + } | |
141 | + if (g_source[g_srcpos]==',') { | |
142 | + g_srcpos++; | |
143 | + } else { | |
144 | + break; | |
145 | + } | |
146 | + } while(1); | |
147 | + return 0; | |
148 | +} | |
149 | + | |
150 | +void* call_clib_init(void** data, void* address){ | |
151 | + // Store gp and ra | |
152 | + asm volatile("#":::"s0"); | |
153 | + asm volatile("#":::"ra"); | |
154 | + asm volatile("addu $t9,$a1,$zero"); | |
155 | + asm volatile("addu $s0,$gp,$zero"); | |
156 | + asm volatile("jalr $ra,$t9"); | |
157 | + asm volatile("addu $gp,$s0,$zero"); | |
158 | +} | |
159 | + | |
160 | +char* clib_main(){ | |
161 | + char* err; | |
162 | + unsigned int begin,end,addr; | |
163 | + void* clibdata; | |
164 | + int* functions; | |
165 | + int* got; | |
166 | + int i,opos,adjust; | |
167 | + char* clib; | |
168 | + int record[3]; | |
169 | + // Insert CMPDATA_USELIB | |
170 | + record[0]=g_clib; | |
171 | + err=cmpdata_insert(CMPDATA_USECLIB,0,&record[0],1); | |
172 | + if (err) return err; | |
173 | + // Determine begin and end addresses | |
174 | + begin=0x000fffff; | |
175 | + end=0; | |
176 | + while(1){ | |
177 | + err=hex_read_line(); | |
178 | + if (err) return err; | |
179 | + if (g_hexline.type==1) { | |
180 | + // EOF | |
181 | + break; | |
182 | + } else if (g_hexline.type==4) { | |
183 | + // extended linear address | |
184 | + addr=g_hexline.data[0]; | |
185 | + addr=addr<<8; | |
186 | + addr|=g_hexline.data[0]; | |
187 | + addr=addr<<16; | |
188 | + } else if (g_hexline.type==0) { | |
189 | + // data | |
190 | + addr&=0xffff0000; | |
191 | + addr|=g_hexline.address; | |
192 | + if (addr<begin) begin=addr; | |
193 | + if (end<addr && addr<0x000fffff) { | |
194 | + end=addr+g_hexline.size; | |
195 | + } | |
196 | + } else { | |
197 | + // Unknown type | |
198 | + return ERR_HEX_ERROR; | |
199 | + } | |
200 | + } | |
201 | + hex_reinit_file(); | |
202 | + // Assign and clear region | |
203 | + check_obj_space((end-begin+3)>>2); | |
204 | + clib=(char*)&g_object[g_objpos]; | |
205 | + got=(int*)&g_object[g_objpos]; | |
206 | + for(i=0;i<((end-begin+3)>>2);i++) g_object[g_objpos++]=0; | |
207 | + // Load binary from HEX file | |
208 | + while(1){ | |
209 | + err=hex_read_line(); | |
210 | + if (err) return err; | |
211 | + if (g_hexline.type==1) { | |
212 | + // EOF | |
213 | + break; | |
214 | + } else if (g_hexline.type==4) { | |
215 | + // extended linear address | |
216 | + addr=g_hexline.data[0]; | |
217 | + addr=addr<<8; | |
218 | + addr|=g_hexline.data[0]; | |
219 | + addr=addr<<16; | |
220 | + } else if (g_hexline.type==0) { | |
221 | + // data | |
222 | + addr&=0xffff0000; | |
223 | + addr|=g_hexline.address; | |
224 | + for(i=0;i<g_hexline.size;i++){ | |
225 | + clib[addr-begin+i]=g_hexline.data[i]; | |
226 | + } | |
227 | + } else { | |
228 | + // Unknown type | |
229 | + return ERR_HEX_ERROR; | |
230 | + } | |
231 | + } | |
232 | + // Calculate the adjustment value. | |
233 | + // Note that the address of clib_init() is 0x8000. | |
234 | + adjust=(int)clib+0x8000-begin-0xA0008000; | |
235 | + // Modify Global Offset Table (GOT) | |
236 | + for(i=0;i<(0x8000-begin)>>2;i++){ | |
237 | + if ((got[i]&0xFFF00000)==0xA0000000) { | |
238 | + got[i]+=adjust; | |
239 | + } | |
240 | + } | |
241 | + // Call the clib_init() to get the address of clibdata array. | |
242 | + clibdata=call_clib_init((void**)&g_data_clib[0],(void*)(0xA0008000+adjust)); | |
243 | + // Check version | |
244 | + if (((int*)clibdata)[0]>SYSVERI) { | |
245 | + return "Newer version of C library than MachiKania cannot be used."; | |
246 | + } | |
247 | + // Get functions array | |
248 | + clibdata=(void*)(((int*)clibdata)[2])+adjust; | |
249 | + functions=clibdata; | |
250 | + // Construct CMPDATA_CLIBFUNC records. | |
251 | + while(clib=(char*)functions[0]){ | |
252 | + clibdata=(void*)functions[1]; | |
253 | + functions+=2; | |
254 | + // clib is function name as string | |
255 | + // clibdata is address of C function | |
256 | + clib+=adjust; | |
257 | + clibdata+=adjust; | |
258 | + i=str_to_name_int(clib); | |
259 | + if (i<65536) return "Wrong C library function name"; | |
260 | + record[0]=g_clib; | |
261 | + record[1]=i; | |
262 | + record[2]=(int)clibdata; | |
263 | + err=cmpdata_insert(CMPDATA_CLIBFUNC,0,&record[0],3); | |
264 | + if (err) return err; | |
265 | + } | |
266 | + // Initial assembly is a jump statement to jump to the the following routine. | |
267 | + g_object[0]=0x08000000 | ((((int)(&g_object[g_objpos]))&0x0FFFFFFF)>>2); // j xxxxxxxx | |
268 | + // Insert initialization code | |
269 | + g_object[g_objpos++]=0x3C050000|((((unsigned int)(0xA0008000+adjust))>>16)&0x0000FFFF); // lui a1,xxxx | |
270 | + g_object[g_objpos++]=0x34A50000|(((unsigned int)(0xA0008000+adjust))&0x0000FFFF); // ori a1,a1,xxxx | |
271 | + call_quicklib_code(call_clib_init,ASM_ADDIU_A0_ZERO_ | 0); | |
272 | + // All done. Shift g_object as the beginning of main BASIC code. | |
273 | + g_object+=g_objpos; | |
274 | + g_objpos=0; | |
275 | + return 0; | |
276 | +} | |
277 | + | |
278 | +char* useclib_begin(char* buff){ | |
279 | + int i,j,cwd_id; | |
280 | + char* err; | |
281 | + char* clibname; | |
282 | + char filename[11]; | |
283 | + int* record; | |
284 | + // Remove a objects before USECLIB statement | |
285 | + g_objpos=0; | |
286 | + // Insert twp NOP assemblies. This will be replaced by branch statement. | |
287 | + check_obj_space(2); | |
288 | + g_object[g_objpos++]=0x00000000; // nop | |
289 | + g_object[g_objpos++]=0x00000000; // nop | |
290 | + // Construct HEX file name to open | |
291 | + clibname=resolve_label(g_clib); | |
292 | + for(i=0;filename[i]=clibname[i];i++); | |
293 | + filename[i++]='.'; | |
294 | + filename[i++]='H'; | |
295 | + filename[i++]='E'; | |
296 | + filename[i++]='X'; | |
297 | + filename[i++]=0; | |
298 | + // Open file in current directory | |
299 | + err=hex_init_file(buff,filename); | |
300 | + if (!err) { | |
301 | + // HEX file found in current directory. | |
302 | + err=clib_main(); | |
303 | + hex_close_file(); | |
304 | + } else { | |
305 | + // Hex file not found in current directory. | |
306 | + // Find it in LIB directory. | |
307 | + if (!FSgetcwd(buff,256)) return ERR_UNKNOWN; | |
308 | + for(i=0;buff[i];i++); | |
309 | + cwd_id=cmpdata_get_id(); | |
310 | + if (!cwd_id) return ERR_UNKNOWN; | |
311 | + err=cmpdata_insert(CMPDATA_TEMP,cwd_id,(int*)(&buff[0]),(i+1+3)>>2); | |
312 | + if (err) return err; | |
313 | + // Change current directory to class library directory | |
314 | + for(i=0;buff[i]="\\LIB\\"[i];i++); | |
315 | + for(j=0;buff[i++]=clibname[j];j++); | |
316 | + buff[i]=0; | |
317 | + FSchdir(buff); | |
318 | + err=hex_init_file(buff,filename); | |
319 | + if (!err) { | |
320 | + // HEX file found in LIB directory | |
321 | + err=clib_main(); | |
322 | + hex_close_file(); | |
323 | + } else { | |
324 | + err=ERR_NO_CLIB; | |
325 | + } | |
326 | + // Restore current dirctory | |
327 | + cmpdata_reset(); | |
328 | + while(record=cmpdata_find(CMPDATA_TEMP)){ | |
329 | + if ((record[0]&0xffff)==cwd_id) break; | |
330 | + } | |
331 | + if (!record) return ERR_UNKNOWN; | |
332 | + FSchdir((char*)(&record[1])); | |
333 | + cmpdata_delete(record); | |
334 | + } | |
335 | + return err; | |
336 | +} | |
337 | + | |
338 | +void lib_clib(int* params, void* address){ | |
339 | + // Store gp and ra | |
340 | + asm volatile("#":::"s0"); | |
341 | + asm volatile("#":::"ra"); | |
342 | + asm volatile("addu $t9,$a1,$zero"); | |
343 | + asm volatile("addu $s0,$gp,$zero"); | |
344 | + asm volatile("lw $a3,16($a0)"); | |
345 | + asm volatile("lw $a2,12($a0)"); | |
346 | + asm volatile("lw $a1,8($a0)"); | |
347 | + asm volatile("lw $a0,4($a0)"); | |
348 | + asm volatile("jalr $ra,$t9"); | |
349 | + asm volatile("addu $gp,$s0,$zero"); | |
350 | +} | |
351 | + | |
352 | +char* clib_method(char type){ | |
353 | + char* err; | |
354 | + int* record; | |
355 | + int clib,func; | |
356 | + int numparams,stack,spos; | |
357 | + // CLIB name | |
358 | + next_position(); | |
359 | + spos=g_srcpos; | |
360 | + clib=check_var_name(); | |
361 | + if (clib<65536) return ERR_SYNTAX; | |
362 | + // Check if the clib exists | |
363 | + cmpdata_reset(); | |
364 | + while (record=cmpdata_find(CMPDATA_USECLIB)){ | |
365 | + if (record[1]==clib) break; | |
366 | + } | |
367 | + if (!record) { | |
368 | + g_srcpos=spos; | |
369 | + return ERR_NO_CLIB; | |
370 | + } | |
371 | + if (g_source[g_srcpos++]!=':') return ERR_SYNTAX; | |
372 | + if (g_source[g_srcpos++]!=':') return ERR_SYNTAX; | |
373 | + // Function name | |
374 | + func=check_var_name(); | |
375 | + if (func<65536) return ERR_SYNTAX; | |
376 | + cmpdata_reset(); | |
377 | + while (record=cmpdata_find(CMPDATA_CLIBFUNC)){ | |
378 | + if (record[1]==clib && record[2]==func) break; | |
379 | + } | |
380 | + if (!record) return "Function not found in the C library"; | |
381 | + // Check type and following syntax | |
382 | + if (type==',') { | |
383 | + // This is CLIB(CLASS:METHOD) style | |
384 | + } else { | |
385 | + // Type is either 0 (integer), $ (string), or # (float) | |
386 | + // This is CLASS::METHOD() style | |
387 | + if (type) { | |
388 | + if (g_source[g_srcpos++]!=type) return ERR_SYNTAX; | |
389 | + } | |
390 | + if (g_source[g_srcpos++]!='(') return ERR_SYNTAX; | |
391 | + } | |
392 | + // Construct parameter(s) | |
393 | + next_position(); | |
394 | + numparams=0; | |
395 | + if (','==type && g_source[g_srcpos]!=',') { | |
396 | + // This is CLIB(CLASS:METHOD) style | |
397 | + // no parameter | |
398 | + } else if (','!=type && g_source[g_srcpos]==')') { | |
399 | + // This is CLASS::METHOD() style | |
400 | + // no parameter | |
401 | + } else { | |
402 | + // There is parameter(s) | |
403 | + do { | |
404 | + numparams++; | |
405 | + if (4<numparams) return ERR_SYNTAX; | |
406 | + else if (1==numparams) { | |
407 | + check_obj_space(1); | |
408 | + stack=g_objpos++; | |
409 | + } | |
410 | + if (g_source[g_srcpos]==',') g_srcpos++; | |
411 | + g_object[stack]=0x27BD0000|(65536-numparams*4); // addiu sp,sp,-xx | |
412 | + err=get_stringFloatOrValue(); | |
413 | + if (err) return err; | |
414 | + check_obj_space(1); | |
415 | + g_object[g_objpos++]=0xAFA20000|(numparams*4); // sw v0,xx(sp) | |
416 | + next_position(); | |
417 | + } while (g_source[g_srcpos]==','); | |
418 | + } | |
419 | + // Call CLIB | |
420 | + check_obj_space(2); | |
421 | + g_object[g_objpos++]=0x3C050000|(((unsigned int)record[3])>>16); // lui a1,xxxx | |
422 | + g_object[g_objpos++]=0x34A50000|(((unsigned int)record[3])&0x0000FFFF); // ori a1,a1,xxxx | |
423 | + call_quicklib_code(lib_clib,ASM_ADDU_A0_SP_ZERO); // All done | |
424 | + check_obj_space(1); | |
425 | + if (numparams) g_object[g_objpos++]=0x27BD0000|(numparams*4); // addiu sp,sp,xx | |
426 | + return 0; | |
427 | +} | |
428 | + | |
429 | +char* clib_statement(){ | |
430 | + return clib_method(','); | |
431 | +} | |
\ No newline at end of file |
@@ -0,0 +1,108 @@ | ||
1 | +<Cライブラリーの利用方法> | |
2 | + | |
3 | +まず、Cライブラリーの使い方について述べます。作成方法については、下の方を参照して | |
4 | +下さい。 | |
5 | + | |
6 | +Cライブラリーの本体は、「*.HEX」ファイルです。拡張子が「HEX」のファイルが、BASIC | |
7 | +プログラムが置かれているのと同じディレクトリーか、LIBディレクトリーの所定の場所に | |
8 | +ある事を確認して下さい。 | |
9 | + | |
10 | +BASICプログラム中では、まず冒頭でUSECLIBステートメントを記述して下さい。 | |
11 | + | |
12 | +USECLIB x[,y[,z[, ... ]]] | |
13 | + Cライブラリーの利用を宣言する。x,y,z等は、ライブラリー名を6文字以内の英数字 | |
14 | + で指定。 | |
15 | + | |
16 | +ここでは、「*.HEX」ファイルのファイル名を、指定します。「TCLIB.HEX」なら | |
17 | +「USECLIB TCLIB」と記述します。 | |
18 | + | |
19 | +Cライブラリー内の関数を呼び出すには、以下のいずれかの方法を取ります。それぞれの | |
20 | +関数の詳しい使用方法については、Cライブラリーに付属のドキュメントを参照して下さ | |
21 | +い。 | |
22 | + | |
23 | +CLIB xxx::yyy[,z1[,z2 ...]] | |
24 | + Cライブラリー内の関数を呼び出す。xxxはライブラリー名、yyyは関数名。z1, z2等 | |
25 | + は引数(オプション)。 | |
26 | +CLIB(xxx::yyy[,z1[,z2 ... ]]) | |
27 | + Cライブラリー内の関数を呼び出し、整数を返す。xxxはライブラリー名、yyyは関数 | |
28 | + 名。z1, z2等は引数(オプション)。xxx::yyy([z1[,z2 ... ]])と書いても同じ。 | |
29 | +CLIB$(xxx::yyy[,z1[,z2 ... ]]) | |
30 | + Cライブラリー内の関数を呼び出し、文字列を返す。xxxはライブラリー名、yyyは関 | |
31 | + 数名。z1, z2等は引数(オプション)。xxx::yyy$([z1[,z2 ... ]])と書いても同じ。 | |
32 | +CLIB#(xxx::yyy[,z1[,z2 ... ]]) | |
33 | + Cライブラリー内の関数を呼び出し、実数を返す。xxxはライブラリー名、yyyは関 | |
34 | + 数名。z1, z2等は引数(オプション)。xxx::yyy#([z1[,z2 ... ]])と書いても同じ。 | |
35 | + | |
36 | +<使用例> | |
37 | + | |
38 | +USECLIB TCLIB | |
39 | +PRINT TCLIB::TEST$(0) | |
40 | +PRINT TCLIB::TEST$(1) | |
41 | + | |
42 | +<Cライブラリーの作成方法> | |
43 | + | |
44 | +Cライブラリーを作製する場合には、MPLAB X IDEとXC32コンパイラーのver 1.42以降が | |
45 | +必要です。 | |
46 | + | |
47 | +まず、ライブラリー作成用のテンプレートをダウンロードして下さい。少なくとも、次の | |
48 | +ファイルが含まれているはずです。 | |
49 | + | |
50 | +clib.c | |
51 | +clib.h | |
52 | +clib_p32MX370F512H.ld | |
53 | +example.c | |
54 | + | |
55 | +「File->Project Properties」を選択します。次の設定を確認し、異なっていれば値を | |
56 | +変更してください。 | |
57 | + Categories: Conf | |
58 | + Compiler Toochains: XC32 (v1.42以降) | |
59 | + Categories: xc32-gcc | |
60 | + Additinal options: -mgen-pie-static | |
61 | + Option categories: Optimization | |
62 | + optimization-level: 1 | |
63 | + Generated Command Line: -g -O1 | |
64 | + Categories: xc32-ld | |
65 | + Additional options: --no-data-init | |
66 | + Option categories: General | |
67 | + Remove unused sections: チェックを入れる | |
68 | + Option categories: Libraries | |
69 | + Exclude Standard Libraries: チェックを入れる | |
70 | + Generated Command Line: --gc-sections --no-code-in-dinit --no-dinit-in-serial-mem -nostdlib -Map="${DISTDIR}/${PROJECTNAME}.${IMAGE_TYPE}.map" | |
71 | + | |
72 | +clib.c, clib.h, clib_p32MX370F512H.ldの3つは、通常は編集せずにそのまま使います。 | |
73 | +example.cを編集(必要ならばファイル名を変更)する事で、Cライブラリーを作製して下さ | |
74 | +い。コンパイルして出来たHEXファイルが、完成した本体です。 | |
75 | + | |
76 | +<Cライブラリーの仕様> | |
77 | + | |
78 | +Cライブラリーを作成するにあたり、以下の規約に従って下さい。 | |
79 | + | |
80 | +1.グローバル変数・スタティック変数領域の容量は、128バイト。 | |
81 | + ・20個ほどのグローバル変数・スタティック変数が使用可能。 | |
82 | + ・大きなメモリー領域が必要な場合は、malloc(), calloc(), free()を使用する。 | |
83 | + ・グローバル変数の初期化は、init()関数で行なわなければならない。 | |
84 | + ・スタティック変数は実行前の初期化はできない(常に0で初期化される)。 | |
85 | + | |
86 | +2.パブリック関数を、その呼び出し名と共にリストアップする事。 | |
87 | + ・functions[]グローバル変数に指定する。 | |
88 | + ・フォーマットについては、example.cを参照。 | |
89 | + | |
90 | +3.パブリック関数の引数は、4つまで。 | |
91 | + | |
92 | +4.割り込みは使用出来ない。 | |
93 | + | |
94 | +<グローバル変数領域のサイズ変更> | |
95 | + | |
96 | +より大きな変数領域が必要な場合は、calloc()で領域を割り当てる事が推奨されます。 | |
97 | +それでも、グローバル変数領域が足りない場合は、以下の方法でサイズ変更出来ます。 | |
98 | + | |
99 | +1.clib_p[32MC370F512H.ldを編集する。 | |
100 | + ・「kseg1_data_mem」の設定の所、「-0x080」と「LENGTH = 0x080」となっている所 | |
101 | + を適当なサイズに変更する。 | |
102 | + | |
103 | +2.clib.hを編集する。 | |
104 | + ・「#define CLIB_DATA_MEM_SIZE 0x0080」の所、上記で変更した値と同じになるよう | |
105 | + に、編集する。 | |
106 | + | |
107 | +<バージョン履歴> | |
108 | +・KM-1209/KM1304 2019年?月公開。 |
@@ -398,6 +398,7 @@ char* coretimer_statement(); | ||
398 | 398 | char* coretimer_function(); |
399 | 399 | char* interrupt_statement(); |
400 | 400 | |
401 | +void init_clib(); | |
401 | 402 | char* useclib_statement(); |
402 | 403 | char* useclib_begin(char* buff); |
403 | 404 | char* clib_method(char type); |
@@ -0,0 +1,271 @@ | ||
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 | +/* | |
9 | + This file is shared by Megalopa and Zoea | |
10 | +*/ | |
11 | + | |
12 | +#include "compiler.h" | |
13 | +#include "api.h" | |
14 | + | |
15 | +/* | |
16 | + Intel HEX format example | |
17 | + :040bf000ffffffcf35 | |
18 | + +--------------------- Byte count | |
19 | + | +---------------- Address | |
20 | + | | +------------- Record type (00:Data, 01:EOF, 04: Extended linear addres | |
21 | + | | | +---- Data | |
22 | + | | | | +- Checksum | |
23 | + | | | | | | |
24 | + : 04 0bf0 00 ffffffcf 35 | |
25 | + : 02 0000 04 1fc0 1b | |
26 | + : 00 0000 01 FF | |
27 | + | |
28 | + Record types: | |
29 | + case 0: // data | |
30 | + case 4: // extended linear address | |
31 | + case 1: // EOF | |
32 | + | |
33 | +*/ | |
34 | + | |
35 | +/* | |
36 | + Example of HEX file | |
37 | + | |
38 | +:020000040000fa | |
39 | +:1080000000001c3c707f9c2721e09903e0ffbd2706 | |
40 | +:108010001c00bfaf1000bcaf0e0080101880828f14 | |
41 | +:10802000000044ac1c80828f80ff42241c80848f1f | |
42 | +:10803000000040a0010042242b184400fdff6054c2 | |
43 | +:10804000000040a02080998f09f820030000000064 | |
44 | +:108050001000bc8f2480828f1c00bf8f0800e003bb | |
45 | +:048060002000bd2718 | |
46 | +:020000040000fa | |
47 | +:107f80000000000000000080a47f00a0008000a08e | |
48 | +:107f9000708000a0fc8000a0000001a0788000a0fc | |
49 | +:047fa00000000000dd | |
50 | +:020000040000fa | |
51 | +:108070000800e0030000000000001c3cf87e9c2784 | |
52 | +:1080800021e09903040080542880828f2880828f09 | |
53 | +:108090000800e003d48042240800e003e480422486 | |
54 | +:1080a00000001c3cd07e9c2721e09903e0ffbd2707 | |
55 | +:1080b0001c00bfaf1000bcaf2c80998f09f82003c3 | |
56 | +:1080c000000000001000bc8f1c00bf8f0800e00300 | |
57 | +:0480d0002000bd27a8 | |
58 | +:020000040000fa | |
59 | +:1080d40048656c6c6f20576f726c6421000000005f | |
60 | +:1080e4005468697320697320612074657374000097 | |
61 | +:0880f400544553540000000044 | |
62 | +:020000040000fa | |
63 | +:1080fc0040010000800000001c8100a00000000076 | |
64 | +:020000040000fa | |
65 | +:10810c0000000000222222222222222222222222cb | |
66 | +:020000040000fa | |
67 | +:0c811c00f48000a0a08000a00000000083 | |
68 | +:00000001FF | |
69 | +*/ | |
70 | + | |
71 | +// Use the same global vars in file.c | |
72 | +extern FSFILE* g_fhandle; | |
73 | +extern char* g_fbuff; | |
74 | +extern int g_size; | |
75 | +extern int g_filepoint; | |
76 | +// Vars used only in this file | |
77 | +static unsigned char g_checksum; | |
78 | + | |
79 | +void hex_read_file(int blocklen){ | |
80 | + int i; | |
81 | + if (blocklen==512) { | |
82 | + // This is first read. Initialize parameter(s). | |
83 | + g_srcpos=0; | |
84 | + g_filepoint=0; | |
85 | + } else if (g_size<512) { | |
86 | + // Already reached the end of file. | |
87 | + return; | |
88 | + } else { | |
89 | + // Shift buffer and source position 256 bytes. | |
90 | + for(i=0;i<256;i++) g_fbuff[i]=g_fbuff[i+256]; | |
91 | + g_srcpos-=256; | |
92 | + g_filepoint+=256; | |
93 | + } | |
94 | + // Read 512 or 256 bytes from SD card. | |
95 | + g_size=512-blocklen+FSfread((void*)&g_fbuff[512-blocklen],1,blocklen,g_fhandle); | |
96 | + // All lower cases | |
97 | + for(i=512-blocklen;i<512;i++){ | |
98 | + if ('A'<=g_fbuff[i] && g_fbuff[i]<='F') g_fbuff[i]+=0x20; | |
99 | + } | |
100 | +} | |
101 | + | |
102 | +int hex_read_byte(){ | |
103 | + unsigned char b1,b2; | |
104 | + b1=g_fbuff[g_srcpos++]; | |
105 | + b2=g_fbuff[g_srcpos++]; | |
106 | + if ('0'<=b1 && b1<='9') { | |
107 | + b1-='0'; | |
108 | + } else if ('a'<=b1 && b1<='f') { | |
109 | + b1-='a'; | |
110 | + b1+=0x0a; | |
111 | + } else { | |
112 | + return -1; | |
113 | + } | |
114 | + if ('0'<=b2 && b2<='9') { | |
115 | + b2-='0'; | |
116 | + } else if ('a'<=b2 && b2<='f') { | |
117 | + b2-='a'; | |
118 | + b2+=0x0a; | |
119 | + } else { | |
120 | + return -1; | |
121 | + } | |
122 | + b1=(b1<<4)|b2; | |
123 | + g_checksum+=b1; | |
124 | + return b1; | |
125 | +} | |
126 | + | |
127 | +char* hex_read_line(){ | |
128 | + int i,j; | |
129 | + // Initialize checksum | |
130 | + g_checksum=0; | |
131 | + // Maintain at least 256 characters in cache. | |
132 | + if (256<=g_srcpos) hex_read_file(256); | |
133 | + // Read a hex file line | |
134 | + if (g_fbuff[g_srcpos++]!=':') return ERR_HEX_ERROR; | |
135 | + // Read size | |
136 | + i=hex_read_byte(); | |
137 | + if (i<0) return ERR_HEX_ERROR; | |
138 | + g_hexline.size=(unsigned char)i; | |
139 | + // Read address | |
140 | + i=hex_read_byte(); | |
141 | + if (i<0) return ERR_HEX_ERROR; | |
142 | + g_hexline.address=(unsigned short)(i<<8); | |
143 | + i=hex_read_byte(); | |
144 | + if (i<0) return ERR_HEX_ERROR; | |
145 | + g_hexline.address|=(unsigned short)(i); | |
146 | + // Ready type | |
147 | + i=hex_read_byte(); | |
148 | + if (i<0) return ERR_HEX_ERROR; | |
149 | + g_hexline.type=(unsigned char)i; | |
150 | + // Read data | |
151 | + for(j=0;j<g_hexline.size;j++){ | |
152 | + i=hex_read_byte(); | |
153 | + if (i<0) return ERR_HEX_ERROR; | |
154 | + g_hexline.data[j]=(unsigned char)i; | |
155 | + } | |
156 | + // Read checksum | |
157 | + i=hex_read_byte(); | |
158 | + if (i<0) return ERR_HEX_ERROR; | |
159 | + if (g_checksum) return ERR_HEX_ERROR; | |
160 | + // All done. Remove enter. | |
161 | + if (g_fbuff[g_srcpos]=='\r') g_srcpos++; | |
162 | + if (g_fbuff[g_srcpos]=='\n') g_srcpos++; | |
163 | + return 0; | |
164 | +} | |
165 | + | |
166 | +static char g_hex_line[47]=":"; | |
167 | +void hex_construct_byte(unsigned char data,int pos){ | |
168 | + g_hex_line[pos+0]="0123456789abcdef"[data>>4]; | |
169 | + g_hex_line[pos+1]="0123456789abcdef"[data&15]; | |
170 | + g_checksum+=data; | |
171 | +} | |
172 | +char* hex_construct_line(){ | |
173 | + int i; | |
174 | + g_checksum=0; | |
175 | + // Write size | |
176 | + hex_construct_byte(g_hexline.size,1); | |
177 | + // Write address | |
178 | + hex_construct_byte(g_hexline.address>>8,3); | |
179 | + hex_construct_byte(g_hexline.address&0xff,5); | |
180 | + // Write type | |
181 | + hex_construct_byte(g_hexline.type,7); | |
182 | + // Write data | |
183 | + for(i=0;i<g_hexline.size;i++){ | |
184 | + hex_construct_byte(g_hexline.data[i],9+i*2); | |
185 | + } | |
186 | + // Write checksum | |
187 | + hex_construct_byte(0-g_checksum,9+i*2); | |
188 | + // All done. Add CRLF and 0x00 | |
189 | + g_hex_line[11+i*2]=0x0d; | |
190 | + g_hex_line[12+i*2]=0x0a; | |
191 | + g_hex_line[13+i*2]=0; | |
192 | + return (char*)&g_hex_line[0]; | |
193 | +} | |
194 | + | |
195 | +void hex_reinit_file(){ | |
196 | + // Go to point 0 | |
197 | + FSfseek(g_fhandle,0,SEEK_SET); | |
198 | + // Initialize parameters | |
199 | + g_srcpos=0; | |
200 | + g_filepoint=0; | |
201 | + // Read first 512 bytes | |
202 | + hex_read_file(512); | |
203 | +} | |
204 | + | |
205 | +char* hex_init_file(char* buff,char* filename){ | |
206 | + // Open file | |
207 | + g_fhandle=FSfopen(filename,"r"); | |
208 | + if (!g_fhandle) { | |
209 | + return ERR_UNKNOWN; | |
210 | + } | |
211 | + // Initialize parameters | |
212 | + g_fbuff=buff; | |
213 | + g_source=buff; | |
214 | + g_srcpos=0; | |
215 | + g_filepoint=0; | |
216 | + // Read first 512 bytes | |
217 | + hex_read_file(512); | |
218 | + return 0; | |
219 | +} | |
220 | + | |
221 | +void hex_close_file(){ | |
222 | + FSfclose(g_fhandle); | |
223 | +} | |
224 | + | |
225 | +char* hex_write(FSFILE* fhandle){ | |
226 | + int i,j; | |
227 | + char* str; | |
228 | + // Construct the line string. | |
229 | + str=hex_construct_line(); | |
230 | + // Determine string length | |
231 | + for(i=0;str[i];i++); | |
232 | + j=FSfwrite(str,1,i,fhandle); | |
233 | + if (j<i) return ERR_FILE; | |
234 | + return 0; | |
235 | +} | |
236 | + | |
237 | + | |
238 | +char* hex_write_address(FSFILE* fhandle,unsigned short addr){ | |
239 | + int i,j; | |
240 | + char* str; | |
241 | + addr&=0x7fff; // Write 0x1d00 instead of 0x9d00. | |
242 | + g_hexline.size=2; | |
243 | + g_hexline.type=4; | |
244 | + g_hexline.address=0; | |
245 | + g_hexline.data[0]=addr>>8; | |
246 | + g_hexline.data[1]=addr&0xff; | |
247 | + return hex_write(fhandle); | |
248 | +} | |
249 | + | |
250 | +char* hex_write_data_16(FSFILE* fhandle,unsigned short addr,unsigned int* object){ | |
251 | + int i,j; | |
252 | + char* str; | |
253 | + g_hexline.size=16; | |
254 | + g_hexline.type=0; | |
255 | + g_hexline.address=addr; | |
256 | + for(i=0;i<4;i++){ | |
257 | + g_hexline.data[i*4+0]=object[i]; | |
258 | + g_hexline.data[i*4+1]=object[i]>>8; | |
259 | + g_hexline.data[i*4+2]=object[i]>>16; | |
260 | + g_hexline.data[i*4+3]=object[i]>>24; | |
261 | + } | |
262 | + return hex_write(fhandle); | |
263 | +} | |
264 | + | |
265 | +char* hex_write_eof(FSFILE* fhandle){ | |
266 | + int i; | |
267 | + i=FSfwrite(":00000001FF\x0d\x0a",1,13,fhandle); | |
268 | + if (i<13) return ERR_FILE; | |
269 | + return 0; | |
270 | +} | |
271 | + |
@@ -46,7 +46,7 @@ int runbasic(char *appname,int mode){ | ||
46 | 46 | // -1:ファイルエラー |
47 | 47 | // -2:リンクエラー |
48 | 48 | // 1以上:コンパイルエラーの発生行(行番号ではなくファイル上の何行目か) |
49 | - int i; | |
49 | + int i,j; | |
50 | 50 | char* buff; |
51 | 51 | char* err; |
52 | 52 |
@@ -85,19 +85,23 @@ int runbasic(char *appname,int mode){ | ||
85 | 85 | // Initialize music system |
86 | 86 | init_music(); |
87 | 87 | |
88 | + // Initialize clib | |
89 | + init_clib(); | |
90 | + | |
88 | 91 | printstr("BASIC "BASVER"\n"); |
89 | 92 | wait60thsec(15); |
90 | 93 | |
91 | 94 | printstr("Compiling..."); |
92 | 95 | |
93 | 96 | if (mode==RUNMODE_COPY_AND_RUN) { |
94 | - // Copy the object from MOS | |
95 | - appname=(char*)MACHIKANIA_OBJ_ADDRESS; | |
96 | - for(i=0;i<RAMSIZE;i++) RAM[i]=appname[i]; | |
97 | 97 | // Set g_object/g_objpos for library functions like lib_read(). |
98 | 98 | // The g_object/g_objpos values are stoared just before MOS. |
99 | 99 | g_object=(int*)g_object_mos; |
100 | 100 | g_objpos=g_objpos_mos; |
101 | + // Copy the object from MOS | |
102 | + j=(int)(&g_object[g_objpos])-(int)(&RAM[0]); | |
103 | + appname=(char*)MACHIKANIA_OBJ_ADDRESS; | |
104 | + for(i=0;i<j;i++) RAM[i]=appname[i]; | |
101 | 105 | } else { |
102 | 106 | // Initialize compiler |
103 | 107 | cmpdata_init(); |
@@ -0,0 +1,431 @@ | ||
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 | +/* | |
9 | + This file is shared by Megalopa and Zoea | |
10 | +*/ | |
11 | + | |
12 | +#include "compiler.h" | |
13 | +#include "api.h" | |
14 | +#include "main.h" | |
15 | + | |
16 | +/* | |
17 | + CMPDATA_USECLIB structure | |
18 | + type: CMPDATA_USECLIB (8) | |
19 | + len: 2 | |
20 | + data16: n/a (0) | |
21 | + record[1]: clib name as integer | |
22 | + | |
23 | + CMPDATA_CLIBFUNC structure | |
24 | + type: CMPDATA_CLIBFUNC (9) | |
25 | + len: 4 | |
26 | + data16: n/a (0) | |
27 | + record[1]: clib name as integer | |
28 | + record[2]: func name as integer | |
29 | + record[3]: pointer to function | |
30 | +*/ | |
31 | + | |
32 | +/* | |
33 | + * g_data_clib[] contains the data from MachiKania compiler for this library | |
34 | + */ | |
35 | +void* g_data_clib_var[]={ | |
36 | + 0, // will be g_gp, g_data[0][0],"0" | |
37 | +}; | |
38 | + | |
39 | +const void* const g_data_clib_core[]={ | |
40 | + lib_calloc_memory,// g_data[1][0],"0" | |
41 | + lib_delete, // g_data[1][1],"4" | |
42 | +}; | |
43 | + | |
44 | +const void* const g_data_clib_file[]={ | |
45 | +#ifdef __DEBUG | |
46 | + 0 // Disabled in debug mode | |
47 | +#else | |
48 | + FSInit, // g_data[2][0],"0" | |
49 | + FSfopen, // g_data[2][1],"4" | |
50 | + FSfclose, // g_data[2][2],"8" | |
51 | + FSfread, // g_data[2][3],"12" | |
52 | + FSfwrite, // g_data[2][4],"16" | |
53 | + FSfeof, // g_data[2][5],"20" | |
54 | + FSftell, // g_data[2][6],"24" | |
55 | + FSfseek, // g_data[2][7],"28" | |
56 | + FSrewind, // g_data[2][8],"32" | |
57 | + FindFirst,// g_data[2][9],"36" | |
58 | + FindNext, // g_data[2][10],"40" | |
59 | + FSmkdir, // g_data[2][11],"44" | |
60 | + FSgetcwd, // g_data[2][12],"48" | |
61 | + FSchdir, // g_data[2][13],"52" | |
62 | + FSremove, // g_data[2][14],"56" | |
63 | + FSrename, // g_data[2][15],"60" | |
64 | +#endif | |
65 | +}; | |
66 | + | |
67 | +const void* const g_data_clib_video[]={ | |
68 | + start_composite,// g_data[3][0],"0" | |
69 | + stop_composite, // g_data[3][1],"4" | |
70 | + printchar, // g_data[3][2],"8" | |
71 | + printstr, // g_data[3][3],"12" | |
72 | + printnum, // g_data[3][4],"16" | |
73 | + printnum2, // g_data[3][5],"20" | |
74 | + cls, // g_data[3][6],"24" | |
75 | + vramscroll, // g_data[3][7],"28" | |
76 | + setcursorcolor, // g_data[3][8],"32" | |
77 | + setcursor, // g_data[3][9],"36" | |
78 | + set_palette, // g_data[3][10],"40" | |
79 | + set_bgcolor, // g_data[3][11],"44" | |
80 | +}; | |
81 | + | |
82 | +const void* const g_data_clib_graphic[]={ | |
83 | + g_pset, // g_data[4][0],"0" | |
84 | + g_putbmpmn, // g_data[4][1],"4" | |
85 | + g_clrbmpmn, // g_data[4][2],"8" | |
86 | + g_gline, // g_data[4][3],"12" | |
87 | + g_hline, // g_data[4][4],"16" | |
88 | + g_circle, // g_data[4][5],"20" | |
89 | + g_circlefill, // g_data[4][6],"24" | |
90 | + g_boxfill, // g_data[4][7],"28" | |
91 | + g_putfont, // g_data[4][8],"32" | |
92 | + g_printstr, // g_data[4][9],"36" | |
93 | + g_printnum, // g_data[4][10],"40" | |
94 | + g_printnum2, // g_data[4][11],"44" | |
95 | + g_color, // g_data[4][12],"48" | |
96 | +}; | |
97 | + | |
98 | +const void* const g_data_clib_keyboard[]={ | |
99 | + shiftkeys, // g_data[5][0],"0" | |
100 | + ps2readkey,// g_data[5][1],"4" | |
101 | +}; | |
102 | + | |
103 | +const void* const g_data_clib[]={ | |
104 | + &g_data_clib_var[0], // g_data[0],"0" | |
105 | + &g_data_clib_core[0], // g_data[1],"4" | |
106 | + &g_data_clib_file[0], // g_data[2],"8" | |
107 | + &g_data_clib_video[0], // g_data[3],"12" | |
108 | + &g_data_clib_graphic[0], // g_data[4],"16" | |
109 | + &g_data_clib_keyboard[0],// g_data[5],"20" | |
110 | +}; | |
111 | + | |
112 | +// CLIB name used (name as 31 bit integer) | |
113 | +static unsigned int g_clib; | |
114 | + | |
115 | +void init_clib(){ | |
116 | + // Initialize g_data_clib_var[] | |
117 | + g_data_clib_var[0]=(void*)g_gp; | |
118 | +} | |
119 | + | |
120 | +char* useclib_statement(){ | |
121 | + int i; | |
122 | + int* cmpdata; | |
123 | + do { | |
124 | + next_position(); | |
125 | + i=check_var_name(); | |
126 | + if (i<65536) return ERR_SYNTAX; | |
127 | + // Check if the clib already exists | |
128 | + cmpdata_reset(); | |
129 | + while(cmpdata=cmpdata_find(CMPDATA_USECLIB)){ | |
130 | + if (cmpdata[1]==i) { | |
131 | + // The clib was already defined. | |
132 | + i=0; | |
133 | + break; | |
134 | + } | |
135 | + } | |
136 | + if (i) { | |
137 | + // Load new file to define clib. | |
138 | + g_clib=i; | |
139 | + return ERR_COMPILE_CLIB; | |
140 | + } | |
141 | + if (g_source[g_srcpos]==',') { | |
142 | + g_srcpos++; | |
143 | + } else { | |
144 | + break; | |
145 | + } | |
146 | + } while(1); | |
147 | + return 0; | |
148 | +} | |
149 | + | |
150 | +void* call_clib_init(void** data, void* address){ | |
151 | + // Store gp and ra | |
152 | + asm volatile("#":::"s0"); | |
153 | + asm volatile("#":::"ra"); | |
154 | + asm volatile("addu $t9,$a1,$zero"); | |
155 | + asm volatile("addu $s0,$gp,$zero"); | |
156 | + asm volatile("jalr $ra,$t9"); | |
157 | + asm volatile("addu $gp,$s0,$zero"); | |
158 | +} | |
159 | + | |
160 | +char* clib_main(){ | |
161 | + char* err; | |
162 | + unsigned int begin,end,addr; | |
163 | + void* clibdata; | |
164 | + int* functions; | |
165 | + int* got; | |
166 | + int i,opos,adjust; | |
167 | + char* clib; | |
168 | + int record[3]; | |
169 | + // Insert CMPDATA_USELIB | |
170 | + record[0]=g_clib; | |
171 | + err=cmpdata_insert(CMPDATA_USECLIB,0,&record[0],1); | |
172 | + if (err) return err; | |
173 | + // Determine begin and end addresses | |
174 | + begin=0x000fffff; | |
175 | + end=0; | |
176 | + while(1){ | |
177 | + err=hex_read_line(); | |
178 | + if (err) return err; | |
179 | + if (g_hexline.type==1) { | |
180 | + // EOF | |
181 | + break; | |
182 | + } else if (g_hexline.type==4) { | |
183 | + // extended linear address | |
184 | + addr=g_hexline.data[0]; | |
185 | + addr=addr<<8; | |
186 | + addr|=g_hexline.data[0]; | |
187 | + addr=addr<<16; | |
188 | + } else if (g_hexline.type==0) { | |
189 | + // data | |
190 | + addr&=0xffff0000; | |
191 | + addr|=g_hexline.address; | |
192 | + if (addr<begin) begin=addr; | |
193 | + if (end<addr && addr<0x000fffff) { | |
194 | + end=addr+g_hexline.size; | |
195 | + } | |
196 | + } else { | |
197 | + // Unknown type | |
198 | + return ERR_HEX_ERROR; | |
199 | + } | |
200 | + } | |
201 | + hex_reinit_file(); | |
202 | + // Assign and clear region | |
203 | + check_obj_space((end-begin+3)>>2); | |
204 | + clib=(char*)&g_object[g_objpos]; | |
205 | + got=(int*)&g_object[g_objpos]; | |
206 | + for(i=0;i<((end-begin+3)>>2);i++) g_object[g_objpos++]=0; | |
207 | + // Load binary from HEX file | |
208 | + while(1){ | |
209 | + err=hex_read_line(); | |
210 | + if (err) return err; | |
211 | + if (g_hexline.type==1) { | |
212 | + // EOF | |
213 | + break; | |
214 | + } else if (g_hexline.type==4) { | |
215 | + // extended linear address | |
216 | + addr=g_hexline.data[0]; | |
217 | + addr=addr<<8; | |
218 | + addr|=g_hexline.data[0]; | |
219 | + addr=addr<<16; | |
220 | + } else if (g_hexline.type==0) { | |
221 | + // data | |
222 | + addr&=0xffff0000; | |
223 | + addr|=g_hexline.address; | |
224 | + for(i=0;i<g_hexline.size;i++){ | |
225 | + clib[addr-begin+i]=g_hexline.data[i]; | |
226 | + } | |
227 | + } else { | |
228 | + // Unknown type | |
229 | + return ERR_HEX_ERROR; | |
230 | + } | |
231 | + } | |
232 | + // Calculate the adjustment value. | |
233 | + // Note that the address of clib_init() is 0x8000. | |
234 | + adjust=(int)clib+0x8000-begin-0xA0008000; | |
235 | + // Modify Global Offset Table (GOT) | |
236 | + for(i=0;i<(0x8000-begin)>>2;i++){ | |
237 | + if ((got[i]&0xFFF00000)==0xA0000000) { | |
238 | + got[i]+=adjust; | |
239 | + } | |
240 | + } | |
241 | + // Call the clib_init() to get the address of clibdata array. | |
242 | + clibdata=call_clib_init((void**)&g_data_clib[0],(void*)(0xA0008000+adjust)); | |
243 | + // Check version | |
244 | + if (((int*)clibdata)[0]>SYSVERI) { | |
245 | + return "Newer version of C library than MachiKania cannot be used."; | |
246 | + } | |
247 | + // Get functions array | |
248 | + clibdata=(void*)(((int*)clibdata)[2])+adjust; | |
249 | + functions=clibdata; | |
250 | + // Construct CMPDATA_CLIBFUNC records. | |
251 | + while(clib=(char*)functions[0]){ | |
252 | + clibdata=(void*)functions[1]; | |
253 | + functions+=2; | |
254 | + // clib is function name as string | |
255 | + // clibdata is address of C function | |
256 | + clib+=adjust; | |
257 | + clibdata+=adjust; | |
258 | + i=str_to_name_int(clib); | |
259 | + if (i<65536) return "Wrong C library function name"; | |
260 | + record[0]=g_clib; | |
261 | + record[1]=i; | |
262 | + record[2]=(int)clibdata; | |
263 | + err=cmpdata_insert(CMPDATA_CLIBFUNC,0,&record[0],3); | |
264 | + if (err) return err; | |
265 | + } | |
266 | + // Initial assembly is a jump statement to jump to the the following routine. | |
267 | + g_object[0]=0x08000000 | ((((int)(&g_object[g_objpos]))&0x0FFFFFFF)>>2); // j xxxxxxxx | |
268 | + // Insert initialization code | |
269 | + g_object[g_objpos++]=0x3C050000|((((unsigned int)(0xA0008000+adjust))>>16)&0x0000FFFF); // lui a1,xxxx | |
270 | + g_object[g_objpos++]=0x34A50000|(((unsigned int)(0xA0008000+adjust))&0x0000FFFF); // ori a1,a1,xxxx | |
271 | + call_quicklib_code(call_clib_init,ASM_ADDIU_A0_ZERO_ | 0); | |
272 | + // All done. Shift g_object as the beginning of main BASIC code. | |
273 | + g_object+=g_objpos; | |
274 | + g_objpos=0; | |
275 | + return 0; | |
276 | +} | |
277 | + | |
278 | +char* useclib_begin(char* buff){ | |
279 | + int i,j,cwd_id; | |
280 | + char* err; | |
281 | + char* clibname; | |
282 | + char filename[11]; | |
283 | + int* record; | |
284 | + // Remove a objects before USECLIB statement | |
285 | + g_objpos=0; | |
286 | + // Insert twp NOP assemblies. This will be replaced by branch statement. | |
287 | + check_obj_space(2); | |
288 | + g_object[g_objpos++]=0x00000000; // nop | |
289 | + g_object[g_objpos++]=0x00000000; // nop | |
290 | + // Construct HEX file name to open | |
291 | + clibname=resolve_label(g_clib); | |
292 | + for(i=0;filename[i]=clibname[i];i++); | |
293 | + filename[i++]='.'; | |
294 | + filename[i++]='H'; | |
295 | + filename[i++]='E'; | |
296 | + filename[i++]='X'; | |
297 | + filename[i++]=0; | |
298 | + // Open file in current directory | |
299 | + err=hex_init_file(buff,filename); | |
300 | + if (!err) { | |
301 | + // HEX file found in current directory. | |
302 | + err=clib_main(); | |
303 | + hex_close_file(); | |
304 | + } else { | |
305 | + // Hex file not found in current directory. | |
306 | + // Find it in LIB directory. | |
307 | + if (!FSgetcwd(buff,256)) return ERR_UNKNOWN; | |
308 | + for(i=0;buff[i];i++); | |
309 | + cwd_id=cmpdata_get_id(); | |
310 | + if (!cwd_id) return ERR_UNKNOWN; | |
311 | + err=cmpdata_insert(CMPDATA_TEMP,cwd_id,(int*)(&buff[0]),(i+1+3)>>2); | |
312 | + if (err) return err; | |
313 | + // Change current directory to class library directory | |
314 | + for(i=0;buff[i]="\\LIB\\"[i];i++); | |
315 | + for(j=0;buff[i++]=clibname[j];j++); | |
316 | + buff[i]=0; | |
317 | + FSchdir(buff); | |
318 | + err=hex_init_file(buff,filename); | |
319 | + if (!err) { | |
320 | + // HEX file found in LIB directory | |
321 | + err=clib_main(); | |
322 | + hex_close_file(); | |
323 | + } else { | |
324 | + err=ERR_NO_CLIB; | |
325 | + } | |
326 | + // Restore current dirctory | |
327 | + cmpdata_reset(); | |
328 | + while(record=cmpdata_find(CMPDATA_TEMP)){ | |
329 | + if ((record[0]&0xffff)==cwd_id) break; | |
330 | + } | |
331 | + if (!record) return ERR_UNKNOWN; | |
332 | + FSchdir((char*)(&record[1])); | |
333 | + cmpdata_delete(record); | |
334 | + } | |
335 | + return err; | |
336 | +} | |
337 | + | |
338 | +void lib_clib(int* params, void* address){ | |
339 | + // Store gp and ra | |
340 | + asm volatile("#":::"s0"); | |
341 | + asm volatile("#":::"ra"); | |
342 | + asm volatile("addu $t9,$a1,$zero"); | |
343 | + asm volatile("addu $s0,$gp,$zero"); | |
344 | + asm volatile("lw $a3,16($a0)"); | |
345 | + asm volatile("lw $a2,12($a0)"); | |
346 | + asm volatile("lw $a1,8($a0)"); | |
347 | + asm volatile("lw $a0,4($a0)"); | |
348 | + asm volatile("jalr $ra,$t9"); | |
349 | + asm volatile("addu $gp,$s0,$zero"); | |
350 | +} | |
351 | + | |
352 | +char* clib_method(char type){ | |
353 | + char* err; | |
354 | + int* record; | |
355 | + int clib,func; | |
356 | + int numparams,stack,spos; | |
357 | + // CLIB name | |
358 | + next_position(); | |
359 | + spos=g_srcpos; | |
360 | + clib=check_var_name(); | |
361 | + if (clib<65536) return ERR_SYNTAX; | |
362 | + // Check if the clib exists | |
363 | + cmpdata_reset(); | |
364 | + while (record=cmpdata_find(CMPDATA_USECLIB)){ | |
365 | + if (record[1]==clib) break; | |
366 | + } | |
367 | + if (!record) { | |
368 | + g_srcpos=spos; | |
369 | + return ERR_NO_CLIB; | |
370 | + } | |
371 | + if (g_source[g_srcpos++]!=':') return ERR_SYNTAX; | |
372 | + if (g_source[g_srcpos++]!=':') return ERR_SYNTAX; | |
373 | + // Function name | |
374 | + func=check_var_name(); | |
375 | + if (func<65536) return ERR_SYNTAX; | |
376 | + cmpdata_reset(); | |
377 | + while (record=cmpdata_find(CMPDATA_CLIBFUNC)){ | |
378 | + if (record[1]==clib && record[2]==func) break; | |
379 | + } | |
380 | + if (!record) return "Function not found in the C library"; | |
381 | + // Check type and following syntax | |
382 | + if (type==',') { | |
383 | + // This is CLIB(CLASS:METHOD) style | |
384 | + } else { | |
385 | + // Type is either 0 (integer), $ (string), or # (float) | |
386 | + // This is CLASS::METHOD() style | |
387 | + if (type) { | |
388 | + if (g_source[g_srcpos++]!=type) return ERR_SYNTAX; | |
389 | + } | |
390 | + if (g_source[g_srcpos++]!='(') return ERR_SYNTAX; | |
391 | + } | |
392 | + // Construct parameter(s) | |
393 | + next_position(); | |
394 | + numparams=0; | |
395 | + if (','==type && g_source[g_srcpos]!=',') { | |
396 | + // This is CLIB(CLASS:METHOD) style | |
397 | + // no parameter | |
398 | + } else if (','!=type && g_source[g_srcpos]==')') { | |
399 | + // This is CLASS::METHOD() style | |
400 | + // no parameter | |
401 | + } else { | |
402 | + // There is parameter(s) | |
403 | + do { | |
404 | + numparams++; | |
405 | + if (4<numparams) return ERR_SYNTAX; | |
406 | + else if (1==numparams) { | |
407 | + check_obj_space(1); | |
408 | + stack=g_objpos++; | |
409 | + } | |
410 | + if (g_source[g_srcpos]==',') g_srcpos++; | |
411 | + g_object[stack]=0x27BD0000|(65536-numparams*4); // addiu sp,sp,-xx | |
412 | + err=get_stringFloatOrValue(); | |
413 | + if (err) return err; | |
414 | + check_obj_space(1); | |
415 | + g_object[g_objpos++]=0xAFA20000|(numparams*4); // sw v0,xx(sp) | |
416 | + next_position(); | |
417 | + } while (g_source[g_srcpos]==','); | |
418 | + } | |
419 | + // Call CLIB | |
420 | + check_obj_space(2); | |
421 | + g_object[g_objpos++]=0x3C050000|(((unsigned int)record[3])>>16); // lui a1,xxxx | |
422 | + g_object[g_objpos++]=0x34A50000|(((unsigned int)record[3])&0x0000FFFF); // ori a1,a1,xxxx | |
423 | + call_quicklib_code(lib_clib,ASM_ADDU_A0_SP_ZERO); // All done | |
424 | + check_obj_space(1); | |
425 | + if (numparams) g_object[g_objpos++]=0x27BD0000|(numparams*4); // addiu sp,sp,xx | |
426 | + return 0; | |
427 | +} | |
428 | + | |
429 | +char* clib_statement(){ | |
430 | + return clib_method(','); | |
431 | +} | |
\ No newline at end of file |
@@ -0,0 +1,108 @@ | ||
1 | +<Cライブラリーの利用方法> | |
2 | + | |
3 | +まず、Cライブラリーの使い方について述べます。作成方法については、下の方を参照して | |
4 | +下さい。 | |
5 | + | |
6 | +Cライブラリーの本体は、「*.HEX」ファイルです。拡張子が「HEX」のファイルが、BASIC | |
7 | +プログラムが置かれているのと同じディレクトリーか、LIBディレクトリーの所定の場所に | |
8 | +ある事を確認して下さい。 | |
9 | + | |
10 | +BASICプログラム中では、まず冒頭でUSECLIBステートメントを記述して下さい。 | |
11 | + | |
12 | +USECLIB x[,y[,z[, ... ]]] | |
13 | + Cライブラリーの利用を宣言する。x,y,z等は、ライブラリー名を6文字以内の英数字 | |
14 | + で指定。 | |
15 | + | |
16 | +ここでは、「*.HEX」ファイルのファイル名を、指定します。「TCLIB.HEX」なら | |
17 | +「USECLIB TCLIB」と記述します。 | |
18 | + | |
19 | +Cライブラリー内の関数を呼び出すには、以下のいずれかの方法を取ります。それぞれの | |
20 | +関数の詳しい使用方法については、Cライブラリーに付属のドキュメントを参照して下さ | |
21 | +い。 | |
22 | + | |
23 | +CLIB xxx::yyy[,z1[,z2 ...]] | |
24 | + Cライブラリー内の関数を呼び出す。xxxはライブラリー名、yyyは関数名。z1, z2等 | |
25 | + は引数(オプション)。 | |
26 | +CLIB(xxx::yyy[,z1[,z2 ... ]]) | |
27 | + Cライブラリー内の関数を呼び出し、整数を返す。xxxはライブラリー名、yyyは関数 | |
28 | + 名。z1, z2等は引数(オプション)。xxx::yyy([z1[,z2 ... ]])と書いても同じ。 | |
29 | +CLIB$(xxx::yyy[,z1[,z2 ... ]]) | |
30 | + Cライブラリー内の関数を呼び出し、文字列を返す。xxxはライブラリー名、yyyは関 | |
31 | + 数名。z1, z2等は引数(オプション)。xxx::yyy$([z1[,z2 ... ]])と書いても同じ。 | |
32 | +CLIB#(xxx::yyy[,z1[,z2 ... ]]) | |
33 | + Cライブラリー内の関数を呼び出し、実数を返す。xxxはライブラリー名、yyyは関 | |
34 | + 数名。z1, z2等は引数(オプション)。xxx::yyy#([z1[,z2 ... ]])と書いても同じ。 | |
35 | + | |
36 | +<使用例> | |
37 | + | |
38 | +USECLIB TCLIB | |
39 | +PRINT TCLIB::TEST$(0) | |
40 | +PRINT TCLIB::TEST$(1) | |
41 | + | |
42 | +<Cライブラリーの作成方法> | |
43 | + | |
44 | +Cライブラリーを作製する場合には、MPLAB X IDEとXC32コンパイラーのver 1.42以降が | |
45 | +必要です。 | |
46 | + | |
47 | +まず、ライブラリー作成用のテンプレートをダウンロードして下さい。少なくとも、次の | |
48 | +ファイルが含まれているはずです。 | |
49 | + | |
50 | +clib.c | |
51 | +clib.h | |
52 | +clib_p32MX370F512H.ld | |
53 | +example.c | |
54 | + | |
55 | +「File->Project Properties」を選択します。次の設定を確認し、異なっていれば値を | |
56 | +変更してください。 | |
57 | + Categories: Conf | |
58 | + Compiler Toochains: XC32 (v1.42以降) | |
59 | + Categories: xc32-gcc | |
60 | + Additinal options: -mgen-pie-static | |
61 | + Option categories: Optimization | |
62 | + optimization-level: 1 | |
63 | + Generated Command Line: -g -O1 | |
64 | + Categories: xc32-ld | |
65 | + Additional options: --no-data-init | |
66 | + Option categories: General | |
67 | + Remove unused sections: チェックを入れる | |
68 | + Option categories: Libraries | |
69 | + Exclude Standard Libraries: チェックを入れる | |
70 | + Generated Command Line: --gc-sections --no-code-in-dinit --no-dinit-in-serial-mem -nostdlib -Map="${DISTDIR}/${PROJECTNAME}.${IMAGE_TYPE}.map" | |
71 | + | |
72 | +clib.c, clib.h, clib_p32MX370F512H.ldの3つは、通常は編集せずにそのまま使います。 | |
73 | +example.cを編集(必要ならばファイル名を変更)する事で、Cライブラリーを作製して下さ | |
74 | +い。コンパイルして出来たHEXファイルが、完成した本体です。 | |
75 | + | |
76 | +<Cライブラリーの仕様> | |
77 | + | |
78 | +Cライブラリーを作成するにあたり、以下の規約に従って下さい。 | |
79 | + | |
80 | +1.グローバル変数・スタティック変数領域の容量は、128バイト。 | |
81 | + ・20個ほどのグローバル変数・スタティック変数が使用可能。 | |
82 | + ・大きなメモリー領域が必要な場合は、malloc(), calloc(), free()を使用する。 | |
83 | + ・グローバル変数の初期化は、init()関数で行なわなければならない。 | |
84 | + ・スタティック変数は実行前の初期化はできない(常に0で初期化される)。 | |
85 | + | |
86 | +2.パブリック関数を、その呼び出し名と共にリストアップする事。 | |
87 | + ・functions[]グローバル変数に指定する。 | |
88 | + ・フォーマットについては、example.cを参照。 | |
89 | + | |
90 | +3.パブリック関数の引数は、4つまで。 | |
91 | + | |
92 | +4.割り込みは使用出来ない。 | |
93 | + | |
94 | +<グローバル変数領域のサイズ変更> | |
95 | + | |
96 | +より大きな変数領域が必要な場合は、calloc()で領域を割り当てる事が推奨されます。 | |
97 | +それでも、グローバル変数領域が足りない場合は、以下の方法でサイズ変更出来ます。 | |
98 | + | |
99 | +1.clib_p[32MC370F512H.ldを編集する。 | |
100 | + ・「kseg1_data_mem」の設定の所、「-0x080」と「LENGTH = 0x080」となっている所 | |
101 | + を適当なサイズに変更する。 | |
102 | + | |
103 | +2.clib.hを編集する。 | |
104 | + ・「#define CLIB_DATA_MEM_SIZE 0x0080」の所、上記で変更した値と同じになるよう | |
105 | + に、編集する。 | |
106 | + | |
107 | +<バージョン履歴> | |
108 | +・KM-1209/KM1304 2019年?月公開。 |
@@ -398,6 +398,7 @@ char* coretimer_statement(); | ||
398 | 398 | char* coretimer_function(); |
399 | 399 | char* interrupt_statement(); |
400 | 400 | |
401 | +void init_clib(); | |
401 | 402 | char* useclib_statement(); |
402 | 403 | char* useclib_begin(char* buff); |
403 | 404 | char* clib_method(char type); |
@@ -0,0 +1,271 @@ | ||
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 | +/* | |
9 | + This file is shared by Megalopa and Zoea | |
10 | +*/ | |
11 | + | |
12 | +#include "compiler.h" | |
13 | +#include "api.h" | |
14 | + | |
15 | +/* | |
16 | + Intel HEX format example | |
17 | + :040bf000ffffffcf35 | |
18 | + +--------------------- Byte count | |
19 | + | +---------------- Address | |
20 | + | | +------------- Record type (00:Data, 01:EOF, 04: Extended linear addres | |
21 | + | | | +---- Data | |
22 | + | | | | +- Checksum | |
23 | + | | | | | | |
24 | + : 04 0bf0 00 ffffffcf 35 | |
25 | + : 02 0000 04 1fc0 1b | |
26 | + : 00 0000 01 FF | |
27 | + | |
28 | + Record types: | |
29 | + case 0: // data | |
30 | + case 4: // extended linear address | |
31 | + case 1: // EOF | |
32 | + | |
33 | +*/ | |
34 | + | |
35 | +/* | |
36 | + Example of HEX file | |
37 | + | |
38 | +:020000040000fa | |
39 | +:1080000000001c3c707f9c2721e09903e0ffbd2706 | |
40 | +:108010001c00bfaf1000bcaf0e0080101880828f14 | |
41 | +:10802000000044ac1c80828f80ff42241c80848f1f | |
42 | +:10803000000040a0010042242b184400fdff6054c2 | |
43 | +:10804000000040a02080998f09f820030000000064 | |
44 | +:108050001000bc8f2480828f1c00bf8f0800e003bb | |
45 | +:048060002000bd2718 | |
46 | +:020000040000fa | |
47 | +:107f80000000000000000080a47f00a0008000a08e | |
48 | +:107f9000708000a0fc8000a0000001a0788000a0fc | |
49 | +:047fa00000000000dd | |
50 | +:020000040000fa | |
51 | +:108070000800e0030000000000001c3cf87e9c2784 | |
52 | +:1080800021e09903040080542880828f2880828f09 | |
53 | +:108090000800e003d48042240800e003e480422486 | |
54 | +:1080a00000001c3cd07e9c2721e09903e0ffbd2707 | |
55 | +:1080b0001c00bfaf1000bcaf2c80998f09f82003c3 | |
56 | +:1080c000000000001000bc8f1c00bf8f0800e00300 | |
57 | +:0480d0002000bd27a8 | |
58 | +:020000040000fa | |
59 | +:1080d40048656c6c6f20576f726c6421000000005f | |
60 | +:1080e4005468697320697320612074657374000097 | |
61 | +:0880f400544553540000000044 | |
62 | +:020000040000fa | |
63 | +:1080fc0040010000800000001c8100a00000000076 | |
64 | +:020000040000fa | |
65 | +:10810c0000000000222222222222222222222222cb | |
66 | +:020000040000fa | |
67 | +:0c811c00f48000a0a08000a00000000083 | |
68 | +:00000001FF | |
69 | +*/ | |
70 | + | |
71 | +// Use the same global vars in file.c | |
72 | +extern FSFILE* g_fhandle; | |
73 | +extern char* g_fbuff; | |
74 | +extern int g_size; | |
75 | +extern int g_filepoint; | |
76 | +// Vars used only in this file | |
77 | +static unsigned char g_checksum; | |
78 | + | |
79 | +void hex_read_file(int blocklen){ | |
80 | + int i; | |
81 | + if (blocklen==512) { | |
82 | + // This is first read. Initialize parameter(s). | |
83 | + g_srcpos=0; | |
84 | + g_filepoint=0; | |
85 | + } else if (g_size<512) { | |
86 | + // Already reached the end of file. | |
87 | + return; | |
88 | + } else { | |
89 | + // Shift buffer and source position 256 bytes. | |
90 | + for(i=0;i<256;i++) g_fbuff[i]=g_fbuff[i+256]; | |
91 | + g_srcpos-=256; | |
92 | + g_filepoint+=256; | |
93 | + } | |
94 | + // Read 512 or 256 bytes from SD card. | |
95 | + g_size=512-blocklen+FSfread((void*)&g_fbuff[512-blocklen],1,blocklen,g_fhandle); | |
96 | + // All lower cases | |
97 | + for(i=512-blocklen;i<512;i++){ | |
98 | + if ('A'<=g_fbuff[i] && g_fbuff[i]<='F') g_fbuff[i]+=0x20; | |
99 | + } | |
100 | +} | |
101 | + | |
102 | +int hex_read_byte(){ | |
103 | + unsigned char b1,b2; | |
104 | + b1=g_fbuff[g_srcpos++]; | |
105 | + b2=g_fbuff[g_srcpos++]; | |
106 | + if ('0'<=b1 && b1<='9') { | |
107 | + b1-='0'; | |
108 | + } else if ('a'<=b1 && b1<='f') { | |
109 | + b1-='a'; | |
110 | + b1+=0x0a; | |
111 | + } else { | |
112 | + return -1; | |
113 | + } | |
114 | + if ('0'<=b2 && b2<='9') { | |
115 | + b2-='0'; | |
116 | + } else if ('a'<=b2 && b2<='f') { | |
117 | + b2-='a'; | |
118 | + b2+=0x0a; | |
119 | + } else { | |
120 | + return -1; | |
121 | + } | |
122 | + b1=(b1<<4)|b2; | |
123 | + g_checksum+=b1; | |
124 | + return b1; | |
125 | +} | |
126 | + | |
127 | +char* hex_read_line(){ | |
128 | + int i,j; | |
129 | + // Initialize checksum | |
130 | + g_checksum=0; | |
131 | + // Maintain at least 256 characters in cache. | |
132 | + if (256<=g_srcpos) hex_read_file(256); | |
133 | + // Read a hex file line | |
134 | + if (g_fbuff[g_srcpos++]!=':') return ERR_HEX_ERROR; | |
135 | + // Read size | |
136 | + i=hex_read_byte(); | |
137 | + if (i<0) return ERR_HEX_ERROR; | |
138 | + g_hexline.size=(unsigned char)i; | |
139 | + // Read address | |
140 | + i=hex_read_byte(); | |
141 | + if (i<0) return ERR_HEX_ERROR; | |
142 | + g_hexline.address=(unsigned short)(i<<8); | |
143 | + i=hex_read_byte(); | |
144 | + if (i<0) return ERR_HEX_ERROR; | |
145 | + g_hexline.address|=(unsigned short)(i); | |
146 | + // Ready type | |
147 | + i=hex_read_byte(); | |
148 | + if (i<0) return ERR_HEX_ERROR; | |
149 | + g_hexline.type=(unsigned char)i; | |
150 | + // Read data | |
151 | + for(j=0;j<g_hexline.size;j++){ | |
152 | + i=hex_read_byte(); | |
153 | + if (i<0) return ERR_HEX_ERROR; | |
154 | + g_hexline.data[j]=(unsigned char)i; | |
155 | + } | |
156 | + // Read checksum | |
157 | + i=hex_read_byte(); | |
158 | + if (i<0) return ERR_HEX_ERROR; | |
159 | + if (g_checksum) return ERR_HEX_ERROR; | |
160 | + // All done. Remove enter. | |
161 | + if (g_fbuff[g_srcpos]=='\r') g_srcpos++; | |
162 | + if (g_fbuff[g_srcpos]=='\n') g_srcpos++; | |
163 | + return 0; | |
164 | +} | |
165 | + | |
166 | +static char g_hex_line[47]=":"; | |
167 | +void hex_construct_byte(unsigned char data,int pos){ | |
168 | + g_hex_line[pos+0]="0123456789abcdef"[data>>4]; | |
169 | + g_hex_line[pos+1]="0123456789abcdef"[data&15]; | |
170 | + g_checksum+=data; | |
171 | +} | |
172 | +char* hex_construct_line(){ | |
173 | + int i; | |
174 | + g_checksum=0; | |
175 | + // Write size | |
176 | + hex_construct_byte(g_hexline.size,1); | |
177 | + // Write address | |
178 | + hex_construct_byte(g_hexline.address>>8,3); | |
179 | + hex_construct_byte(g_hexline.address&0xff,5); | |
180 | + // Write type | |
181 | + hex_construct_byte(g_hexline.type,7); | |
182 | + // Write data | |
183 | + for(i=0;i<g_hexline.size;i++){ | |
184 | + hex_construct_byte(g_hexline.data[i],9+i*2); | |
185 | + } | |
186 | + // Write checksum | |
187 | + hex_construct_byte(0-g_checksum,9+i*2); | |
188 | + // All done. Add CRLF and 0x00 | |
189 | + g_hex_line[11+i*2]=0x0d; | |
190 | + g_hex_line[12+i*2]=0x0a; | |
191 | + g_hex_line[13+i*2]=0; | |
192 | + return (char*)&g_hex_line[0]; | |
193 | +} | |
194 | + | |
195 | +void hex_reinit_file(){ | |
196 | + // Go to point 0 | |
197 | + FSfseek(g_fhandle,0,SEEK_SET); | |
198 | + // Initialize parameters | |
199 | + g_srcpos=0; | |
200 | + g_filepoint=0; | |
201 | + // Read first 512 bytes | |
202 | + hex_read_file(512); | |
203 | +} | |
204 | + | |
205 | +char* hex_init_file(char* buff,char* filename){ | |
206 | + // Open file | |
207 | + g_fhandle=FSfopen(filename,"r"); | |
208 | + if (!g_fhandle) { | |
209 | + return ERR_UNKNOWN; | |
210 | + } | |
211 | + // Initialize parameters | |
212 | + g_fbuff=buff; | |
213 | + g_source=buff; | |
214 | + g_srcpos=0; | |
215 | + g_filepoint=0; | |
216 | + // Read first 512 bytes | |
217 | + hex_read_file(512); | |
218 | + return 0; | |
219 | +} | |
220 | + | |
221 | +void hex_close_file(){ | |
222 | + FSfclose(g_fhandle); | |
223 | +} | |
224 | + | |
225 | +char* hex_write(FSFILE* fhandle){ | |
226 | + int i,j; | |
227 | + char* str; | |
228 | + // Construct the line string. | |
229 | + str=hex_construct_line(); | |
230 | + // Determine string length | |
231 | + for(i=0;str[i];i++); | |
232 | + j=FSfwrite(str,1,i,fhandle); | |
233 | + if (j<i) return ERR_FILE; | |
234 | + return 0; | |
235 | +} | |
236 | + | |
237 | + | |
238 | +char* hex_write_address(FSFILE* fhandle,unsigned short addr){ | |
239 | + int i,j; | |
240 | + char* str; | |
241 | + addr&=0x7fff; // Write 0x1d00 instead of 0x9d00. | |
242 | + g_hexline.size=2; | |
243 | + g_hexline.type=4; | |
244 | + g_hexline.address=0; | |
245 | + g_hexline.data[0]=addr>>8; | |
246 | + g_hexline.data[1]=addr&0xff; | |
247 | + return hex_write(fhandle); | |
248 | +} | |
249 | + | |
250 | +char* hex_write_data_16(FSFILE* fhandle,unsigned short addr,unsigned int* object){ | |
251 | + int i,j; | |
252 | + char* str; | |
253 | + g_hexline.size=16; | |
254 | + g_hexline.type=0; | |
255 | + g_hexline.address=addr; | |
256 | + for(i=0;i<4;i++){ | |
257 | + g_hexline.data[i*4+0]=object[i]; | |
258 | + g_hexline.data[i*4+1]=object[i]>>8; | |
259 | + g_hexline.data[i*4+2]=object[i]>>16; | |
260 | + g_hexline.data[i*4+3]=object[i]>>24; | |
261 | + } | |
262 | + return hex_write(fhandle); | |
263 | +} | |
264 | + | |
265 | +char* hex_write_eof(FSFILE* fhandle){ | |
266 | + int i; | |
267 | + i=FSfwrite(":00000001FF\x0d\x0a",1,13,fhandle); | |
268 | + if (i<13) return ERR_FILE; | |
269 | + return 0; | |
270 | +} | |
271 | + |
@@ -46,7 +46,7 @@ int runbasic(char *appname,int mode){ | ||
46 | 46 | // -1:ファイルエラー |
47 | 47 | // -2:リンクエラー |
48 | 48 | // 1以上:コンパイルエラーの発生行(行番号ではなくファイル上の何行目か) |
49 | - int i; | |
49 | + int i,j; | |
50 | 50 | char* buff; |
51 | 51 | char* err; |
52 | 52 |
@@ -85,19 +85,23 @@ int runbasic(char *appname,int mode){ | ||
85 | 85 | // Initialize music system |
86 | 86 | init_music(); |
87 | 87 | |
88 | + // Initialize clib | |
89 | + init_clib(); | |
90 | + | |
88 | 91 | printstr("BASIC "BASVER"\n"); |
89 | 92 | wait60thsec(15); |
90 | 93 | |
91 | 94 | printstr("Compiling..."); |
92 | 95 | |
93 | 96 | if (mode==RUNMODE_COPY_AND_RUN) { |
94 | - // Copy the object from MOS | |
95 | - appname=(char*)MACHIKANIA_OBJ_ADDRESS; | |
96 | - for(i=0;i<RAMSIZE;i++) RAM[i]=appname[i]; | |
97 | 97 | // Set g_object/g_objpos for library functions like lib_read(). |
98 | 98 | // The g_object/g_objpos values are stoared just before MOS. |
99 | 99 | g_object=(int*)g_object_mos; |
100 | 100 | g_objpos=g_objpos_mos; |
101 | + // Copy the object from MOS | |
102 | + j=(int)(&g_object[g_objpos])-(int)(&RAM[0]); | |
103 | + appname=(char*)MACHIKANIA_OBJ_ADDRESS; | |
104 | + for(i=0;i<j;i++) RAM[i]=appname[i]; | |
101 | 105 | } else { |
102 | 106 | // Initialize compiler |
103 | 107 | cmpdata_init(); |