• R/O
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

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

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


Commit MetaInfo

Revision149 (tree)
Time2016-08-05 03:39:28
Authorkmorimatsu

Log Message

Update trunk with MachiKania type Z ver 1.00

Change Summary

Incremental Difference

--- mips/trunk/music.c (revision 148)
+++ mips/trunk/music.c (revision 149)
@@ -7,7 +7,7 @@
77
88 #include <xc.h>
99 #include "compiler.h"
10-#include "colortext32.h"
10+#include "api.h"
1111
1212 /*
1313 Timer3: 1/32 prescaler, toggle mode : 894886.25 Hz
@@ -166,8 +166,8 @@
166166 T3CON=0x0050; // Prescaller: 1:32 (1.8 MHz), not yet started
167167
168168 // Timer4 is used to intterupt every 1/60 sec, just after NTSC view.
169- T4CON=0x0050; // Prescaller: 1:32
170- PR4=29736; // 3632*262/32-1
169+ T4CON=0x0040; // Prescaller: 1:16
170+ PR4=59473; // 3632*262/16-1
171171 // Timer 4 interruption, IPL3
172172 IPC4bits.T4IP=3;
173173 IPC4bits.T4IS=0;
@@ -348,7 +348,7 @@
348348 g_soundrepeat=g_soundstart=g_soundend=0;
349349 pos=0;
350350 do {
351- while(data[1]!=0x00000021) data++; // Seek DATA statement
351+ while(data[1]!=0x00000020) data++; // Seek DATA statement
352352 datalen=(data[0]&0x00007FFF)-1; // Use bgezal statement containing data length.
353353 data+=2;
354354 while(0<datalen){
@@ -357,6 +357,12 @@
357357 sound=data[0]&0x0000FFFF;
358358 data++;
359359 if (len) {
360+ // Shift tone if graphic is used
361+ if (g_use_graphic) {
362+ // MUL_15 instead of MUL_16 for CPU clock.
363+ // sound=sound*15/16
364+ sound-=(sound+7)>>4;
365+ }
360366 g_sound[pos]=sound-1;
361367 g_soundlen[pos]=len;
362368 pos++;
@@ -452,6 +458,12 @@
452458 g_mspos++;
453459 len=len/musicGetNum();
454460 }
461+ // Shift tone if graphic is used
462+ if (g_use_graphic) {
463+ // MUL_15 instead of MUL_16 for CPU clock.
464+ // tone=tone*15/16
465+ tone-=(tone+7)>>4;
466+ }
455467 // Update music value array
456468 IEC0bits.T4IE=0; // Stop interruption, first.
457469 if (g_musicstart==g_musicend) {
--- mips/trunk/function.c (revision 148)
+++ mips/trunk/function.c (revision 149)
@@ -18,7 +18,16 @@
1818 return 0;
1919 }
2020
21+char* cread_function(){
22+ call_lib_code(LIB_CREAD);
23+ return 0;
24+}
25+
2126 char* gosub_function(){
27+ // Check if garbage collection has been done.
28+ // This check is required because the used temporary area would be changed
29+ // in sub routine.
30+ if (g_temp_area_used) return ERR_GOSUB_ASH;
2231 return gosub_statement();
2332 }
2433 char* strncmp_function(){
@@ -227,6 +236,202 @@
227236 return 0;
228237 }
229238
239+char* args_function(void){
240+ char* err;
241+ int i;
242+ err=get_value();
243+ if (err) return err;
244+ i=g_object[g_objpos-1];
245+ if ((i>>16)==0x3402) {
246+ // Previous object is "ori v0,zero,xxxx".
247+ i&=0xffff;
248+ i=(i+1)<<2;
249+ g_object[g_objpos-1]=0x8EA20000|i; // lw v0,xx(s5)
250+ } else {
251+ check_obj_space(3);
252+ g_object[g_objpos++]=0x00021080; // sll v0,v0,0x2
253+ g_object[g_objpos++]=0x02A21021; // addu v0,s5,v0
254+ g_object[g_objpos++]=0x8C420004; // lw v0,4(v0)
255+ }
256+ return 0;
257+}
258+
259+char* system_function(void){
260+ char* err;
261+ err=get_value();
262+ if (err) return err;
263+ g_object[g_objpos++]=0x00402021; // addu a0,v0,zero
264+ call_lib_code(LIB_SYSTEM);
265+ return 0;
266+}
267+
268+char* sprintf_function(void){
269+ char* err;
270+ err=get_string();
271+ if (err) return err;
272+ next_position();
273+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
274+ g_srcpos++;
275+ check_obj_space(2);
276+ g_object[g_objpos++]=0x27BDFFFC; //addiu sp,sp,-4
277+ g_object[g_objpos++]=0xAFA20004; //sw v0,4(sp)
278+ err=get_float();
279+ if (err) return err;
280+ check_obj_space(3);
281+ g_object[g_objpos++]=0x00022021; //addu a0,zero,v0
282+ g_object[g_objpos++]=0x8FA20004; //lw v0,4(sp)
283+ g_object[g_objpos++]=0x27BD0004; //addiu sp,sp,4
284+ call_lib_code(LIB_SPRINTF);
285+ return 0;
286+}
287+
288+char* floatstr_function(void){
289+ char* err;
290+ err=get_float();
291+ if (err) return err;
292+ check_obj_space(2);
293+ g_object[g_objpos++]=0x00022021; //addu a0,zero,v0
294+ g_object[g_objpos++]=0x34020000; //ori v0,zero,0x0000
295+ call_lib_code(LIB_SPRINTF);
296+ return 0;
297+}
298+
299+char* floatsharp_function(void){
300+ char* err;
301+ err=get_value();
302+ if (err) return err;
303+ check_obj_space(1);
304+ g_object[g_objpos++]=0x34050000|(FUNC_FLOAT&0x0000ffff);// ori a1,zero,xxxx
305+ call_lib_code(LIB_FLOATFUNCS);
306+ return 0;
307+}
308+
309+char* valsharp_function(void){
310+ char* err;
311+ err=get_string();
312+ if (err) return err;
313+ check_obj_space(1);
314+ g_object[g_objpos++]=0x34050000|(FUNC_VALSHARP&0x0000ffff);// ori a1,zero,xxxx
315+ call_lib_code(LIB_FLOATFUNCS);
316+ return 0;
317+}
318+
319+char* int_function(void){
320+ char* err;
321+ err=get_float();
322+ if (err) return err;
323+ check_obj_space(1);
324+ g_object[g_objpos++]=0x34050000|(FUNC_INT&0x0000ffff);// ori a1,zero,xxxx
325+ call_lib_code(LIB_FLOATFUNCS);
326+ return 0;
327+}
328+
329+char* float_constant(float val){
330+ volatile int i;
331+ ((float*)(&i))[0]=val;
332+ if (i&0xFFFF0000) {
333+ // 32 bit
334+ check_obj_space(2);
335+ g_object[g_objpos++]=0x3C020000|((i>>16)&0x0000FFFF); // lui v0,xxxx
336+ g_object[g_objpos++]=0x34420000|(i&0x0000FFFF); // ori v0,v0,xxxx
337+ } else {
338+ // 16 bit
339+ check_obj_space(1);
340+ g_object[g_objpos++]=0x34020000|(i&0x0000FFFF); // ori v0,zero,xxxx
341+ }
342+ return 0;
343+}
344+
345+char* float_1param_function(enum functions func){
346+ char* err;
347+ err=get_float();
348+ if (err) return err;
349+ check_obj_space(1);
350+ g_object[g_objpos++]=0x34050000|(func&0x0000ffff);// ori a1,zero,xxxx
351+ call_lib_code(LIB_FLOATFUNCS);
352+ return 0;
353+}
354+
355+char* float_2param_function(enum functions func){
356+ char* err;
357+ err=get_float();
358+ if (err) return err;
359+ next_position();
360+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
361+ g_srcpos++;
362+ check_obj_space(2);
363+ g_object[g_objpos++]=0x27BDFFFC; //addiu sp,sp,-4
364+ g_object[g_objpos++]=0xAFA20004; //sw v0,4(sp)
365+ err=get_float();
366+ if (err) return err;
367+ check_obj_space(4);
368+ g_object[g_objpos++]=0x00022021; //addu a0,zero,v0
369+ g_object[g_objpos++]=0x8FA20004; //lw v0,4(sp)
370+ g_object[g_objpos++]=0x27BD0004; //addiu sp,sp,4
371+ g_object[g_objpos++]=0x34050000|(func&0x0000ffff);// ori a1,zero,xxxx
372+ call_lib_code(LIB_FLOATFUNCS);
373+ return 0;
374+}
375+
376+char* float_function(void){
377+ char* err;
378+ if (nextCodeIs("FLOAT#(")) {
379+ err=floatsharp_function();
380+ } else if (nextCodeIs("VAL#(")) {
381+ err=valsharp_function();
382+ } else if (nextCodeIs("SIN#(")) {
383+ err=float_1param_function(FUNC_SIN);
384+ } else if (nextCodeIs("COS#(")) {
385+ err=float_1param_function(FUNC_COS);
386+ } else if (nextCodeIs("TAN#(")) {
387+ err=float_1param_function(FUNC_TAN);
388+ } else if (nextCodeIs("ASIN#(")) {
389+ err=float_1param_function(FUNC_ASIN);
390+ } else if (nextCodeIs("ACOS#(")) {
391+ err=float_1param_function(FUNC_ACOS);
392+ } else if (nextCodeIs("ATAN#(")) {
393+ err=float_1param_function(FUNC_ATAN);
394+ } else if (nextCodeIs("SINH#(")) {
395+ err=float_1param_function(FUNC_SINH);
396+ } else if (nextCodeIs("COSH#(")) {
397+ err=float_1param_function(FUNC_COSH);
398+ } else if (nextCodeIs("TANH#(")) {
399+ err=float_1param_function(FUNC_TANH);
400+ } else if (nextCodeIs("EXP#(")) {
401+ err=float_1param_function(FUNC_EXP);
402+ } else if (nextCodeIs("LOG#(")) {
403+ err=float_1param_function(FUNC_LOG);
404+ } else if (nextCodeIs("LOG10#(")) {
405+ err=float_1param_function(FUNC_LOG10);
406+ } else if (nextCodeIs("POW#(")) {
407+ err=float_2param_function(FUNC_POW);
408+ } else if (nextCodeIs("SQRT#(")) {
409+ err=float_1param_function(FUNC_SQRT);
410+ } else if (nextCodeIs("CEIL#(")) {
411+ err=float_1param_function(FUNC_CEIL);
412+ } else if (nextCodeIs("FLOOR#(")) {
413+ err=float_1param_function(FUNC_FLOOR);
414+ } else if (nextCodeIs("FABS#(")) {
415+ err=float_1param_function(FUNC_FABS);
416+ } else if (nextCodeIs("MODF#(")) {
417+ err=float_1param_function(FUNC_MODF);
418+ } else if (nextCodeIs("FMOD#(")) {
419+ err=float_2param_function(FUNC_FMOD);
420+ } else if (nextCodeIs("GOSUB#(")) {
421+ err=gosub_function();
422+ } else if (nextCodeIs("ARGS#(")) {
423+ err=args_function();
424+ } else if (nextCodeIs("PI#")) {
425+ return float_constant(3.141593);
426+ } else {
427+ return ERR_SYNTAX;
428+ }
429+ if (err) return err;
430+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
431+ g_srcpos++;
432+ return 0;
433+}
434+
230435 char* str_function(void){
231436 char* err;
232437 if (nextCodeIs("CHR$(")) {
@@ -237,6 +442,18 @@
237442 err=dec_function();
238443 } else if (nextCodeIs("INPUT$(")) {
239444 err=input_function();
445+ } else if (nextCodeIs("GOSUB$(")) {
446+ err=gosub_function();
447+ } else if (nextCodeIs("ARGS$(")) {
448+ err=args_function();
449+ } else if (nextCodeIs("READ$(")) {
450+ err=read_function();
451+ } else if (nextCodeIs("SPRINTF$(")) {
452+ err=sprintf_function();
453+ } else if (nextCodeIs("FLOAT$(")) {
454+ err=floatstr_function();
455+ } else if (nextCodeIs("SYSTEM$(")) {
456+ err=system_function();
240457 } else {
241458 return ERR_SYNTAX;
242459 }
@@ -260,6 +477,8 @@
260477 err=keys_function();
261478 } else if (nextCodeIs("READ(")) {
262479 err=read_function();
480+ } else if (nextCodeIs("CREAD(")) {
481+ err=cread_function();
263482 } else if (nextCodeIs("GOSUB(")) {
264483 err=gosub_function();
265484 } else if (nextCodeIs("STRNCMP(")) {
@@ -280,6 +499,14 @@
280499 err=val_function();
281500 } else if (nextCodeIs("INKEY(")) {
282501 err=inkey_function();
502+ } else if (nextCodeIs("ARGS(")) {
503+ err=args_function();
504+ } else if (nextCodeIs("SYSTEM(")) {
505+ err=system_function();
506+ } else if (nextCodeIs("INT(")) {
507+ err=int_function();
508+ } else if (nextCodeIs("GCOLOR(")) {
509+ err=graphic_statement(FUNC_GCOLOR);
283510 } else {
284511 return ERR_SYNTAX;
285512 }
@@ -288,18 +515,3 @@
288515 g_srcpos++;
289516 return err;
290517 }
291-
292-/*
293-int g_v0;
294-int g_v1;
295-int test(int v0,int v1){
296- g_v1=g_v0>0?g_v0:-g_v0;
297- asm volatile("addiu $v1,$v0,-1");
298- asm volatile("loop:");
299- asm volatile("lb $a0,1($v1)");
300- asm volatile("addiu $v1,$v1,1");
301- asm volatile("bne $a0,$zero,loop");
302- asm volatile("subu $v0,$v1,$v0");
303- return v0*v1;
304-}
305-//*/
--- mips/trunk/globalvars.c (revision 148)
+++ mips/trunk/globalvars.c (revision 149)
@@ -1,14 +1,16 @@
11 /*
22 This file is provided under the LGPL license ver 2.1.
3- Written by Katsumi.
3+ Written by K.Tanaka & Katsumi
4+ http://www.ze.em-net.ne.jp/~kenken/index.html
45 http://hp.vector.co.jp/authors/VA016157/
5- kmorimatsu@users.sourceforge.jp
66 */
77
88 #include "compiler.h"
9+#include "main.h"
910
10-// Contain the valus of $gp (GPR of MIPS32)
11+// Contain the valus of $gp and $s6 (GPR of MIPS32)
1112 int g_gp;
13+int g_s6;
1214
1315 // Line data when compiling
1416 int g_line;
@@ -23,6 +25,14 @@
2325 int g_sdepth;
2426 int g_maxsdepth;
2527
28+// Following var shows what type of variable was defined
29+// in compiling the last code.
30+enum variable g_lastvar;
31+
32+// Vars used for handling constant integer
33+int g_intconst;
34+char g_valueisconst;
35+
2636 // Global vars associated to RAM
2737 char* g_source;
2838 int g_srcpos;
@@ -29,7 +39,8 @@
2939 int* g_object;
3040 int g_objpos;
3141 int* g_objmax;
32-char RAM[RAMSIZE] __attribute__((persistent,address(0xA0008000-RAMSIZE)));
42+char RAM[RAMSIZE] __attribute__((persistent,address(0xA0000000+PIC32MX_RAMSIZE-PERSISTENT_RAM_SIZE)));
43+unsigned int g_ex_data[EXCEPTION_DATA_SIZE/4] __attribute__((persistent,address(0xA0000000+PIC32MX_RAMSIZE-EXCEPTION_DATA_SIZE)));
3344
3445 // Global area for vars A-Z and three temporary string pointers
3546 int g_var_mem[ALLOC_BLOCK_NUM];
@@ -36,6 +47,9 @@
3647 unsigned short g_var_pointer[ALLOC_BLOCK_NUM];
3748 unsigned short g_var_size[ALLOC_BLOCK_NUM];
3849
50+// Flag to use temporary area when compiling
51+char g_temp_area_used;
52+
3953 // Heap area
4054 int* g_heap_mem;
4155 int g_max_mem;
@@ -48,3 +62,10 @@
4862
4963 // Font data used for PCG
5064 unsigned char* g_pcg_font;
65+
66+// Use or do not use graphic
67+char g_use_graphic;
68+
69+// Pointer to graphic RAM
70+unsigned short* g_graphic_area;
71+
--- mips/trunk/run.c (revision 148)
+++ mips/trunk/run.c (revision 149)
@@ -9,13 +9,8 @@
99 #include "api.h"
1010 #include "compiler.h"
1111 #include "editor.h"
12+#include "main.h"
1213
13-/* Prototypes */
14-char* init_file(char* buff,char* appname);
15-char* compile_file();
16-void wait60thsec(unsigned short n);
17-extern FSFILE* g_fhandle;
18-
1914 char* printdec(int num){
2015 char str[11];
2116 int i;
@@ -67,11 +62,14 @@
6762 return -1;
6863 }
6964
65+ // Initialize parameters
7066 g_pcg_font=0;
71- g_rnd_seed=0x3045;
67+ g_use_graphic=0;
68+ g_graphic_area=0;
7269 clearscreen();
73- setcursor(0,0,7);
74- printstr("BASIC KM-1120\n");
70+ setcursor(0,0,7);
71+
72+ printstr("BASIC "BASVER"\n");
7573 wait60thsec(15);
7674 // Initialize music
7775 init_music();
@@ -80,7 +78,7 @@
8078
8179 // Compile the file
8280 err=compile_file();
83- FSfclose(g_fhandle);
81+ close_file();
8482 if (err) {
8583 // Compile error
8684 printstr(err);
@@ -112,6 +110,21 @@
112110 if(test) return 0; //コンパイルのみの場合
113111 wait60thsec(15);
114112
113+ // Initialize the other parameters
114+ // Random seed
115+ g_rnd_seed=2463534242;
116+ // Clear variables
117+ for(i=0;i<ALLOC_BLOCK_NUM;i++){
118+ g_var_mem[i]=0;
119+ g_var_size[i]=0;
120+ }
121+ // Clear key input buffer
122+ for(i=0;i<256;i++){
123+ ps2keystatus[i]=0;
124+ }
125+ // Reset data/read.
126+ reset_dataread();
127+
115128 // Assign memory
116129 set_free_area((void*)(g_object+g_objpos),(void*)(&RAM[RAMSIZE]));
117130 // Execute program
@@ -119,6 +132,8 @@
119132 // Work area (used for A-Z values) is next to the object code area.
120133 start_program((void*)(&(RAM[0])),(void*)(&g_var_mem[0]));
121134 printstr("\nOK\n");
135+ set_graphmode(0);
136+ g_use_graphic=0;
122137
123138 return 0;
124139 }
--- mips/trunk/statement.c (revision 148)
+++ mips/trunk/statement.c (revision 149)
@@ -8,6 +8,18 @@
88 #include "api.h"
99 #include "compiler.h"
1010
11+char* rem_statement(){
12+ if (g_source[g_srcpos-4]<0x20) {
13+ // This line contains only "REM" statement
14+ // Delete $s6-setting command if exists.
15+ if ((g_object[g_objpos-1]&0xffff0000)==0x34160000) g_objpos--;
16+ }
17+ while(0x20<=g_source[g_srcpos]){
18+ g_srcpos++;
19+ }
20+ return 0;
21+}
22+
1123 char* sound_statement(){
1224 char *err;
1325 err=get_label();
@@ -42,21 +54,13 @@
4254 b1=g_source[g_srcpos];
4355 while('0'<=b1 && b1<='9' || b1=='-' || b1=='$'){
4456 prevpos=g_objpos;
57+ g_valueisconst=1;
4558 err=get_simple_value();
59+ if (!g_valueisconst) err=ERR_SYNTAX;
4660 if (err) return err;
47- if (g_objpos==prevpos+1) {
48- // 16 bit value was taken
49- i=g_object[g_objpos-1]&0x0000FFFF;
50- } else if (g_objpos==prevpos+2) {
51- // 32 bit value was taken
52- i=g_object[g_objpos-2]&0x0000FFFF;
53- i<<=16;
54- i|=g_object[g_objpos-1]&0x0000FFFF;
55- } else {
56- return ERR_SYNTAX;
57- }
61+ check_obj_space(1);
5862 g_objpos=prevpos;
59- g_object[g_objpos++]=i;
63+ g_object[g_objpos++]=g_intconst;
6064 next_position();
6165 b1=g_source[g_srcpos];
6266 if (b1!=',') break;
@@ -63,26 +67,123 @@
6367 g_srcpos++;
6468 next_position();
6569 b1=g_source[g_srcpos];
70+ if (b1==0x0d || b1==0x0a) {
71+ // Multiline DATA/EXEC statement
72+ g_line++;
73+ g_fileline++;
74+ if (b1==0x0D && g_source[g_srcpos+1]==0x0A) g_srcpos++;
75+ g_srcpos++;
76+ // Maintain at least 256 characters in cache.
77+ if (256<=g_srcpos) read_file(256);
78+ next_position();
79+ b1=g_source[g_srcpos];
80+ }
6681 }
6782 return 0;
6883 }
6984
70-char* data_statement(){
71- // 0x00000021(addu zero,zero,zero) is the sign of data region
72- int i,prevpos;
85+char* cdata_statement(){
86+ // 0x00000020, 0x00000021, 0x00000022, and 0x00000023 (add/addu/sub/subu zero,zero,zero)
87+ // are the sign of data region
88+ int beginpos,prevpos;
7389 char* err;
74- prevpos=g_objpos;
90+ char b1;
91+ char* cpy;
92+ int shift=0;
93+ int i=0;
94+ beginpos=g_objpos;
7595 check_obj_space(2);
7696 g_object[g_objpos++]=0x04110000; // bgezal zero,xxxx
77- g_object[g_objpos++]=0x00000021; // addu zero,zero,zero
78- err=exec_statement();
79- if (err) return err;
97+ g_object[g_objpos++]=0x00000020; // add zero,zero,zero
98+ next_position();
99+ b1=g_source[g_srcpos];
100+ while('0'<=b1 && b1<='9' || b1=='-' || b1=='$'){
101+ prevpos=g_objpos;
102+ g_valueisconst=1;
103+ err=get_simple_value();
104+ if (!g_valueisconst) err=ERR_SYNTAX;
105+ if (g_intconst<0x00 || 0xff<g_intconst) err=ERR_SYNTAX;
106+ if (err) return err;
107+ g_objpos=prevpos;
108+ i|=g_intconst<<shift;
109+ shift+=8;
110+ if (32<=shift) {
111+ check_obj_space(1);
112+ g_object[g_objpos++]=i;
113+ shift=0;
114+ i=0;
115+ }
116+ next_position();
117+ b1=g_source[g_srcpos];
118+ if (b1!=',') break;
119+ g_srcpos++;
120+ next_position();
121+ b1=g_source[g_srcpos];
122+ if (b1==0x0d || b1==0x0a) {
123+ // Multiline CDATA statement
124+ g_line++;
125+ g_fileline++;
126+ if (b1==0x0D && g_source[g_srcpos+1]==0x0A) g_srcpos++;
127+ g_srcpos++;
128+ // Maintain at least 256 characters in cache.
129+ if (256<=g_srcpos) read_file(256);
130+ next_position();
131+ b1=g_source[g_srcpos];
132+ }
133+ }
134+ // Write the last 1-3 bytes and shift data if total # is not multipes of 4.
135+ if (0<shift) {
136+ // Convert shift value from bit-shift to data byte-shift.
137+ shift=4-shift/8;
138+ check_obj_space(1);
139+ g_object[g_objpos++]=i;
140+ for(cpy=(char*)&g_object[g_objpos]-1;(char*)&g_object[beginpos+2]<cpy;cpy--){
141+ cpy[0]=cpy[0-shift];
142+ }
143+ }
80144 // Determine the size of data
81- i=g_objpos-prevpos-1;
82- g_object[prevpos]=0x04110000|i; // bgezal zero,xxxx
145+ i=g_objpos-beginpos-1;
146+ g_object[beginpos] =0x04110000|i; // bgezal zero,xxxx
147+ g_object[beginpos+1]=0x00000020|shift; // add zero,zero,zero
83148 return 0;
84149 }
85150
151+char* data_statement(){
152+ // 0x00000020, 0x00000021, 0x00000022, and 0x00000023 (add/addu/sub/subu zero,zero,zero)
153+ // are the sign of data region
154+ int i,prevpos;
155+ char* err;
156+ while(1){
157+ prevpos=g_objpos;
158+ check_obj_space(2);
159+ g_object[g_objpos++]=0x04110000; // bgezal zero,xxxx
160+ g_object[g_objpos++]=0x00000020; // add zero,zero,zero
161+ next_position();
162+ if (g_source[g_srcpos]=='"') {
163+ // Constant string
164+ // Store pointer to string. This is 3 words bellow of current position
165+ g_object[g_objpos]=(int)(&g_object[g_objpos+3]);
166+ g_objpos++;
167+ g_object[prevpos]=0x04110002; // bgezal zero,xxxx
168+ err=simple_string();
169+ if (err) return err;
170+ next_position();
171+ if (g_source[g_srcpos]==',') continue;
172+ return 0;
173+ }
174+ err=exec_statement();
175+ if (err) return err;
176+ // Determine the size of data
177+ i=g_objpos-prevpos-1;
178+ g_object[prevpos]=0x04110000|i; // bgezal zero,xxxx
179+ if (g_source[g_srcpos]=='"') {
180+ // Constant string
181+ continue;
182+ }
183+ return 0;
184+ }
185+}
186+
86187 char* clear_statement(){
87188 call_lib_code(LIB_CLEAR);
88189 return 0;
@@ -109,26 +210,44 @@
109210 char* dim_statement(){
110211 char* err;
111212 char b1;
213+ int spos;
214+ int stack;
112215 while(1){
216+ stack=0;
113217 next_position();
114218 b1=g_source[g_srcpos];
115219 if (b1<'A' || 'Z'<b1) return ERR_SYNTAX;
116220 g_srcpos++;
221+ if (g_source[g_srcpos]=='#') g_srcpos++;
117222 next_position();
118223 if (g_source[g_srcpos]!='(') return ERR_SYNTAX;
119- g_srcpos++;
120- err=get_value();
121- if (err) return err;
224+ check_obj_space(1);
225+ spos=g_objpos++; // addiu sp,sp,xxxx
226+ do {
227+ g_srcpos++;
228+ err=get_value();
229+ if (err) return err;
230+ stack+=4;
231+ check_obj_space(1);
232+ g_object[g_objpos++]=0xAFA20000|stack; // sw v0,8(sp)
233+ } while (g_source[g_srcpos]==',');
122234 if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
123235 g_srcpos++;
124- check_obj_space(2);
125- g_object[g_objpos++]=0x24040000|(b1-'A'); //addiu a0,zero,xx
236+ check_obj_space(3);
237+ g_object[g_objpos++]=0x24040000|(b1-'A'); // addiu a0,zero,xx
238+ g_object[g_objpos++]=0x24050000|(stack/4); // addiu a1,zero,xxxx
239+ g_object[g_objpos++]=0x03A01025; // or v0,sp,zero
126240 call_lib_code(LIB_DIM);
241+ // Stack -/+
242+ check_obj_space(1);
243+ g_object[g_objpos++]=0x27BD0000|stack; // addiu sp,sp,xxxx
244+ stack=(0-stack)&0x0000FFFF;
245+ g_object[spos]=0x27BD0000|stack; // addiu sp,sp,xxxx
127246 next_position();
128247 if (g_source[g_srcpos]!=',') break;
129248 g_srcpos++;
130249 }
131- return 0;
250+ return 0;
132251 }
133252
134253 char* label_statement(){
@@ -157,16 +276,11 @@
157276 if (err) return err;
158277 if (g_label) {
159278 // Constant label/number
160- if (g_label<65536) {
161- // 16 bit
162- check_obj_space(1);
163- g_object[g_objpos++]=0x34020000|g_label; // ori v0,zero,xxxx
164- } else {
165- // 32 bit
166- check_obj_space(2);
167- g_object[g_objpos++]=0x3C020000|(g_label>>16); // lui v0,xxxx
168- g_object[g_objpos++]=0x34420000|(g_label&0x0000FFFF); // ori v0,v0,xxxx
169- }
279+ // Use 32 bit mode also for values<65536
280+ // This code will be replaced to code for v0 for pointer in linker.
281+ check_obj_space(2);
282+ g_object[g_objpos++]=0x3C020000|(g_label>>16); // lui v0,xxxx
283+ g_object[g_objpos++]=0x34420000|(g_label&0x0000FFFF); // ori v0,v0,xxxx
170284 } else {
171285 // Dynamic number
172286 err=get_value();
@@ -176,7 +290,7 @@
176290 return 0;
177291 }
178292
179-char* gosub_statement(){
293+char* gosub_statement_sub(){
180294 char* err;
181295 err=get_label();
182296 if (err) return err;
@@ -211,6 +325,50 @@
211325 return 0;
212326 }
213327
328+char* gosub_statement(){
329+ char* err;
330+ int opos,spos,stack;
331+ opos=g_objpos;
332+ spos=g_srcpos;
333+ err=gosub_statement_sub();
334+ if (err) return err;
335+ next_position();
336+ // If there is no 2nd argument, return.
337+ if (g_source[g_srcpos]!=',') return 0;
338+
339+ // There is (at least) 2nd argument.
340+ // Rewind object and construct argument-creating routine.
341+ g_objpos=opos;
342+ stack=4;
343+ g_object[g_objpos++]=0x27BD0000; // addiu sp,sp,-xx
344+ do {
345+ g_srcpos++;
346+ stack+=4;
347+ err=get_stringFloatOrValue();
348+ if (err) return err;
349+ check_obj_space(1);
350+ g_object[g_objpos++]=0xAFA20000|stack; // sw v0,xx(sp)
351+ next_position();
352+ } while(g_source[g_srcpos]==',');
353+ check_obj_space(2);
354+ g_object[g_objpos++]=0xAFB50004; // sw s5,4(sp)
355+ g_object[g_objpos++]=0x03A0A821; // addu s5,sp,zero
356+ g_object[opos]|=((0-stack)&0xFFFF); // addiu sp,sp,-xx (See above)
357+ // Rewind source and construct GOSUB routine again.
358+ opos=spos;
359+ spos=g_srcpos;
360+ g_srcpos=opos;
361+ err=gosub_statement_sub();
362+ if (err) return err;
363+ // Remove stack
364+ check_obj_space(2);
365+ g_object[g_objpos++]=0x8FB50004; // lw s5,4(sp)
366+ g_object[g_objpos++]=0x27BD0000|stack; // addiu sp,sp,xx
367+ // All done, go back to wright source position
368+ g_srcpos=spos;
369+ return 0;
370+}
371+
214372 char* return_statement(){
215373 char* err;
216374 char b1;
@@ -218,7 +376,7 @@
218376 b1=g_source[g_srcpos];
219377 if (0x20<b1 && b1!=':') {
220378 // There is a return value.
221- err=get_value();
379+ err=get_stringFloatOrValue();
222380 if (err) return err;
223381 }
224382 check_obj_space(3);
@@ -255,16 +413,31 @@
255413 char* err;
256414 int prevpos,bpos;
257415 // Get value.
258- err=get_value();
416+ err=get_floatOrValue();
259417 if (err) return err;
260418 // Check "THEN"
261- if (!nextCodeIs("THEN ")) return ERR_SYNTAX;
419+ if (!nextCodeIs("THEN")) return ERR_SYNTAX;
420+ // Check if statement follows after THEN statement
421+ next_position();
422+ if (nextCodeIs("REM")) {
423+ // If REM statement follows, skip comment words.
424+ rem_statement();
425+ }
426+ if (g_source[g_srcpos]<0x20) {
427+ // End of line.
428+ // Use IF-THEN-ENDIF mode (multiple line mode)
429+ check_obj_space(3);
430+ g_object[g_objpos++]=0x30000000; // nop (see linker)
431+ g_object[g_objpos++]=0x10400000; // beq v0,zero,xxxx
432+ g_object[g_objpos++]=0x30000000; // nop (see linker)
433+ return 0;
434+ }
435+ // One line mode
262436 // If $v0=0 then skip.
263437 bpos=g_objpos;
264438 check_obj_space(2);
265439 g_object[g_objpos++]=0x10400000; // beq v0,zero,xxxx
266440 g_object[g_objpos++]=0x00000000; // nop
267- // Next statement is either label or general statement
268441 prevpos=g_srcpos;
269442 if (statement()) {
270443 // May be label
@@ -315,8 +488,61 @@
315488 return 0;
316489 }
317490
491+char* elseif_statement(void){
492+ // Multiple line mode
493+ char* err;
494+ g_object[g_objpos++]=0x08160100; // breakif (see linker)
495+ g_object[g_objpos++]=0x30008000; // nop (see linker)
496+ // Get value.
497+ err=get_floatOrValue();
498+ if (err) return err;
499+ // Check "THEN"
500+ if (!nextCodeIs("THEN")) return ERR_SYNTAX;
501+ // Check if statement follows after THEN statement
502+ next_position();
503+ if (nextCodeIs("REM")) {
504+ // If REM statement follows, skip comment words.
505+ rem_statement();
506+ }
507+ if (0x20<=g_source[g_srcpos]) return ERR_SYNTAX;
508+ // Statement didn't follow after THEM statement (that is correct).
509+ g_object[g_objpos++]=0x10400000; // beq v0,zero,xxxx
510+ g_object[g_objpos++]=0x30000000; // nop (see linker)
511+ return 0;
512+
513+}
318514
515+char* else_statement(void){
516+ // Multiple line mode
517+ g_object[g_objpos++]=0x08160100; // breakif (see linker)
518+ g_object[g_objpos++]=0x30008000; // nop (see linker)
519+ g_object[g_objpos++]=0x30000000; // nop (see linker)
520+ // Check if statement follows after THEN statement
521+ next_position();
522+ if (nextCodeIs("REM")) {
523+ // If REM statement follows, skip comment words.
524+ rem_statement();
525+ }
526+ if (0x20<=g_source[g_srcpos]) return ERR_SYNTAX;
527+ // Statement didn't follow after THEM statement (that is correct).
528+ return 0;
529+}
319530
531+char* endif_statement(void){
532+ // Multiple line mode
533+ g_object[g_objpos++]=0x30008000; // nop (see linker)
534+ g_object[g_objpos++]=0x30008000; // nop (see linker)
535+ // Check if statement follows after THEN statement
536+ next_position();
537+ if (nextCodeIs("REM")) {
538+ // If REM statement follows, skip comment words.
539+ rem_statement();
540+ }
541+ if (0x20<=g_source[g_srcpos]) return ERR_SYNTAX;
542+ // Statement didn't follow after THEM statement (that is correct).
543+ return 0;
544+}
545+
320546 char* end_statement(void){
321547 int i;
322548 i=(int)&g_end_addr;
@@ -328,17 +554,70 @@
328554 return 0;
329555 }
330556
557+char* let_dim_sub(char b1){
558+ char* err;
559+ g_srcpos++;
560+ err=get_value();
561+ if (err) return err;
562+ check_obj_space(4);
563+ g_object[g_objpos++]=0x00021080; // sll v0,v0,0x2
564+ g_object[g_objpos++]=0x8FC30000|((b1-'A')*4); // lw v1,xx(s8)
565+ g_object[g_objpos++]=0x00621821; // addu v1,v1,v0
566+ g_object[g_objpos++]=0xAFA30004; // sw v1,4(sp)
567+ while(g_source[g_srcpos]==','){
568+ g_srcpos++;
569+ err=get_value();
570+ if (err) return err;
571+ check_obj_space(4);
572+ g_object[g_objpos++]=0x00021080; // sll v0,v0,0x2
573+ g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp)
574+ g_object[g_objpos++]=0x8C630000; // lw v1,0(v1)
575+ g_object[g_objpos++]=0x00621821; // addu v1,v1,v0
576+ g_object[g_objpos++]=0xAFA30004; // sw v1,4(sp)
577+ }
578+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
579+ g_srcpos++;
580+ return 0;
581+};
331582
332583 char* let_statement(){
333584 char* err;
334- char b1,b2;
585+ char b1,b2,b3;
335586 int i;
336587 next_position();
337588 b1=g_source[g_srcpos];
338589 b2=g_source[g_srcpos+1];
590+ b3=g_source[g_srcpos+2];
339591 if (b1<'A' || 'Z'<b1) return ERR_SYNTAX;
340592 g_srcpos++;
341- if (b2=='$') {
593+ if (b2=='#' && b3=='(') {
594+ // Float dimension
595+ g_srcpos++;
596+ check_obj_space(1);
597+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
598+ let_dim_sub(b1);
599+ next_position();
600+ if (g_source[g_srcpos]!='=') return ERR_SYNTAX;
601+ g_srcpos++;
602+ err=get_float();
603+ if (err) return err;
604+ check_obj_space(3);
605+ g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp)
606+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
607+ g_object[g_objpos++]=0xAC620000; // sw v0,0(v1)
608+ return 0;
609+ } else if (b2=='#') {
610+ // Float A-Z
611+ g_srcpos++;
612+ next_position();
613+ if (g_source[g_srcpos]!='=') return ERR_SYNTAX;
614+ g_srcpos++;
615+ err=get_float();
616+ if (err) return err;
617+ check_obj_space(1);
618+ g_object[g_objpos++]=0xAFC20000|((b1-'A')*4); // sw v0,xxx(s8)
619+ return 0;
620+ } else if (b2=='$') {
342621 // String
343622 g_srcpos++;
344623 next_position();
@@ -352,17 +631,9 @@
352631 return 0;
353632 } else if (b2=='(') {
354633 // Dimension
355- g_srcpos++;
356- err=get_value();
357- if (err) return err;
358- if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
359- g_srcpos++;
360- check_obj_space(5);
361- g_object[g_objpos++]=0x00021080; // sll v0,v0,0x2
362- g_object[g_objpos++]=0x8FC30000|((b1-'A')*4); // lw v1,xx(s8)
363- g_object[g_objpos++]=0x00621821; // addu v1,v1,v0
634+ check_obj_space(1);
364635 g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
365- g_object[g_objpos++]=0xAFA30004; // sw v1,4(sp)
636+ let_dim_sub(b1);
366637 next_position();
367638 if (g_source[g_srcpos]!='=') return ERR_SYNTAX;
368639 g_srcpos++;
@@ -389,7 +660,7 @@
389660 char* print_statement(){
390661 char* err;
391662 char b1;
392- int i,prevpos;
663+ int i;
393664 int status=0;// 1:',' 2:';' 0:none
394665 while(1){
395666 next_position();
@@ -396,17 +667,23 @@
396667 b1=g_source[g_srcpos];
397668 if (b1<0x20 || b1==':') break;
398669 if (!strncmp(g_source+g_srcpos,"ELSE " ,5)) break;
399- prevpos=g_objpos;
400- err=get_string();
401- if (err) {
402- // Restore changes caused by trying get_string().
403- g_objpos=prevpos;
404- g_sdepth=0;
405- // May be integer
406- err=get_value();
407- if (err) return err;
408- // Use DEC$() function.
409- call_lib_code(LIB_DEC);
670+ err=get_stringFloatOrValue();
671+ if (err) return err;
672+ switch(g_lastvar){
673+ case VAR_INTEGER:
674+ // Use DEC$() function.
675+ call_lib_code(LIB_DEC);
676+ break;
677+ case VAR_FLOAT:
678+ // Use FLOAT$() function.
679+ check_obj_space(2);
680+ g_object[g_objpos++]=0x00022021; //addu a0,zero,v0
681+ g_object[g_objpos++]=0x34020000; //ori v0,zero,0x0000
682+ call_lib_code(LIB_SPRINTF);
683+ break;
684+ case VAR_STRING:
685+ default:
686+ break;
410687 }
411688 // Call printstr() function
412689 // First argument is the pointer to string
@@ -435,6 +712,14 @@
435712 }
436713 return 0;
437714 }
715+
716+char* break_statement(){
717+ check_obj_space(2);
718+ g_object[g_objpos++]=0x08160000; // j xxxx (See link() function)
719+ g_object[g_objpos++]=0x00000000; // nop
720+ return 0;
721+}
722+
438723 char* for_statement(){
439724 char* err;
440725 char b1;
@@ -455,10 +740,11 @@
455740 // 4(sp): Address to return to in "NEXT" statement.
456741 // Store "TO" value in stack
457742 check_obj_space(2);
458- g_object[g_objpos++]=0x27BDFFF4; // addiu sp,sp,-12
743+ g_object[g_objpos++]=0x0820FFF4; // addiu sp,sp,-12 (see linker)
459744 g_object[g_objpos++]=0xAFA2000C; // sw v0,12(sp)
460745 // Check if "STEP" exists
461746 next_position();
747+ g_valueisconst=1;
462748 if (nextCodeIs("STEP ")) {
463749 // "STEP" exists. Get value
464750 err=get_value();
@@ -467,51 +753,133 @@
467753 // "STEP" not exist. Use "1".
468754 check_obj_space(1);
469755 g_object[g_objpos++]=0x24020001; // addiu v0,zero,1
756+ g_intconst=1;
470757 }
471- // Store "STEP" value in stack and jump to start address
472- // while store return address to $ra.
473- check_obj_space(11);
474- g_object[g_objpos++]=0x04110009; // bgezal zero,label1
475- g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
758+ check_obj_space(14);
759+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp) (STEP value)
760+ g_object[g_objpos++]=0x04110004; // bgezal zero,check
761+ g_object[g_objpos++]=0x8FC40000|((b1-'A')*4); // lw a0,xx(s8) (current var value)
476762 // After executing "NEXT" statement, process reaches following line.
477- // Go to next step and check if variable reachs "TO" value.
478- // Note that $v1 is set to 12($sp) in NEXT statement.
479- // If yes, exit FOR-NEXT loop while restore stack pointer.
480- // Note that $ra contain the address to go to.
481- g_object[g_objpos++]=0x8FC20000|((b1-'A')*4); // lw v0,xx(s8)
482- g_object[g_objpos++]=0x14430003; // bne v0,v1,label0
483- g_object[g_objpos++]=0x8FA30008; // lw v1,8(sp)
484- g_object[g_objpos++]=0x03E00008; // jr ra
485- g_object[g_objpos++]=0x27BD000C; // addiu sp,sp,12
486- // label0
487- g_object[g_objpos++]=0x00431021; // addu v0,v0,v1
488- g_object[g_objpos++]=0x10000002; // beq zero,zero,label2
489- g_object[g_objpos++]=0xAFC20000|((b1-'A')*4); // sw v0,xx(s8)
490- // label1:
763+ // Update variable value by adding STEP value
764+ // Note that STEP value is loaded onto $v0 in NEXT statement
765+ g_object[g_objpos++]=0x8FC40000|((b1-'A')*4); // lw a0,xx(s8) (current var value)
766+ g_object[g_objpos++]=0x00822021; // addu a0,a0,v0
767+ g_object[g_objpos++]=0xAFC40000|((b1-'A')*4); // sw a0,xx(s8) (new var value)
768+ // Value-checking routine and storing ra in stack
769+ // check:
770+ g_object[g_objpos++]=0x8FA3000C; // lw v1,12(sp) (TO value)
771+ g_object[g_objpos++]=0x00641823; // subu v1,v1,a0
772+ g_object[g_objpos++]=0x04420001; // bltzl v0,negative
773+ g_object[g_objpos++]=0x00031823; // subu v1,zero,v1
774+ // negative:
775+ g_object[g_objpos++]=0x04610003; // bgez v1,continue
491776 g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp)
492- // label2:
777+ break_statement(); // (2 words)
778+ // continue:
493779 return 0;
494780 }
495781
496782 char* next_statement(){
497783 // Return to address stored in 4($sp)
498- // while set $v1 to 8($sp) (see for_statement)
499- // and store return address to exit FOR-NEXT loop.
500- check_obj_space(3);
501- g_object[g_objpos++]=0x8FA20004; // lw v0,4(sp)
502- g_object[g_objpos++]=0x0040F809; // jalr ra,v0
503- g_object[g_objpos++]=0x8FA3000C; // lw v1,12(sp)
784+ // while set $v0 to 8($sp) (see for_statement)
785+ check_obj_space(4);
786+ g_object[g_objpos++]=0x8FBF0004; // lw ra,4(sp)
787+ g_object[g_objpos++]=0x03E00008; // jr ra
788+ g_object[g_objpos++]=0x8FA20008; // lw v0,8(sp) (STEP value)
789+ g_object[g_objpos++]=0x0830000C; // addiu sp,sp,12 (see linker)
504790 return 0;
505791 }
506792
507-char* rem_statement(){
508- while(0x20<=g_source[g_srcpos]){
509- g_srcpos++;
793+char* do_statement(){
794+ char* err;
795+ // Usage of stack:
796+ // 4(sp): Address to return to in "DO" statement.
797+ check_obj_space(3);
798+ g_object[g_objpos++]=0x04110001;// bgezal zero,label1:
799+ g_object[g_objpos++]=0x0822FFFC;// addiu sp,sp,-4 (see linker)
800+ // label1:
801+ g_object[g_objpos++]=0xAFBF0004;// sw ra,4(sp)
802+ next_position();
803+ if (nextCodeIs("WHILE ")) {
804+ // DO WHILE
805+ err=get_floatOrValue();
806+ if (err) return err;
807+ check_obj_space(2);
808+ g_object[g_objpos++]=0x14400003; // bne v0,zero,labe2
809+ g_object[g_objpos++]=0x00000000; // nop
810+ return break_statement(); // (2 words)
811+ // label2:
812+
813+ } else if (nextCodeIs("UNTIL ")) {
814+ // DO UNTIL
815+ err=get_floatOrValue();
816+ if (err) return err;
817+ check_obj_space(2);
818+ g_object[g_objpos++]=0x10400003; // beq v0,zero,label2
819+ g_object[g_objpos++]=0x00000000; // nop
820+ return break_statement(); // (2 words)
821+ // label2:
822+ } else {
823+ // DO statement without WHILE/UNTIL
824+ return 0;
510825 }
826+}
827+
828+char* loop_statement(){
829+ char* err;
830+ next_position();
831+ if (nextCodeIs("WHILE ")) {
832+ // LOOP WHILE
833+ err=get_floatOrValue();
834+ if (err) return err;
835+ check_obj_space(1);
836+ g_object[g_objpos++]=0x10400003; // beq v0,zero,label1
837+ } else if (nextCodeIs("UNTIL ")) {
838+ // LOOP UNTIL
839+ err=get_floatOrValue();
840+ if (err) return err;
841+ check_obj_space(1);
842+ g_object[g_objpos++]=0x14400003; // bne v0,zero,label
843+ } else {
844+ // LOOP statement without WHILE/UNTIL
845+ }
846+ check_obj_space(4);
847+ g_object[g_objpos++]=0x8FBF0004; // lw ra,4(sp)
848+ g_object[g_objpos++]=0x03E00008; // jr ra
849+ g_object[g_objpos++]=0x00000000; // nop
850+ // label1:
851+ g_object[g_objpos++]=0x08320004; // addiu sp,sp,4 (See link() function)
511852 return 0;
512853 }
513854
514-char* palette_statement(){
855+char* while_statement(){
856+ char* err;
857+ check_obj_space(3);
858+ g_object[g_objpos++]=0x04110001; // bgezal zero,label1:
859+ g_object[g_objpos++]=0x0821FFFC; // addiu sp,sp,-4 (see linker)
860+ // label1:
861+ g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp)
862+ err=get_floatOrValue();
863+ if (err) return err;
864+ check_obj_space(2);
865+ g_object[g_objpos++]=0x14400003; // bne v0,zero,label2
866+ g_object[g_objpos++]=0x00000000; // nop
867+ return break_statement(); // (2 words)
868+ // label2:
869+}
870+
871+char* wend_statement(){
872+ check_obj_space(4);
873+ g_object[g_objpos++]=0x8FBF0004; // lw ra,4(sp)
874+ g_object[g_objpos++]=0x03E00008; // jr ra
875+ g_object[g_objpos++]=0x00000000; // nop
876+ // label1:
877+ g_object[g_objpos++]=0x08310004; // addiu sp,sp,4 (See link() function)
878+ return 0;
879+}
880+
881+char* palette_statement(enum libs lib){
882+ // lib is either LIB_PALETTE or LIB_GPALETTE
515883 // PALETTE N,R,G,B
516884 char* err;
517885 // Get N
@@ -547,7 +915,7 @@
547915 g_object[g_objpos++]=0x8FA4000C; // lw a0,12(sp)
548916 g_object[g_objpos++]=0x27BD000C; // addiu sp,sp,12
549917 // a0=N, a1=(R<<16)|G, v0=B
550- call_lib_code(LIB_PALETTE);
918+ call_lib_code(lib);
551919 return 0;
552920 }
553921
@@ -604,11 +972,30 @@
604972 return 0;
605973 }
606974
975+char* usegraphic_statement(){
976+ int objpos=g_objpos;
977+ if (get_value()) {
978+ // Getting integer failed.
979+ // It supporsed to be not parameter
980+ // and same as parameter=1.
981+ g_objpos=objpos;
982+ check_obj_space(1);
983+ g_object[g_objpos++]=0x34020001; //ori v0,zero,0x01
984+ }
985+ call_lib_code(LIB_USEGRAPHIC);
986+ return 0;
987+}
988+
607989 char* cls_statement(){
608990 call_lib_code(LIB_CLS);
609991 return 0;
610992 }
611993
994+char* gcls_statement(){
995+ call_lib_code(LIB_GCLS);
996+ return 0;
997+}
998+
612999 char* color_statement(){
6131000 char* err;
6141001 err=get_value();
@@ -617,6 +1004,14 @@
6171004 return 0;
6181005 }
6191006
1007+char* gcolor_statement(){
1008+ char* err;
1009+ err=get_value();
1010+ if (err) return err;
1011+ call_lib_code(LIB_GCOLOR);
1012+ return 0;
1013+}
1014+
6201015 char* param2_statement(enum libs lib){
6211016 char* err;
6221017 // Get 1st
@@ -637,6 +1032,11 @@
6371032 return 0;
6381033 }
6391034
1035+char* system_statement(){
1036+ // SYSTEM X,Y
1037+ return param2_statement(LIB_SYSTEM);
1038+}
1039+
6401040 char* cursor_statement(){
6411041 // CURSOR X,Y
6421042 return param2_statement(LIB_CURSOR);
@@ -643,7 +1043,7 @@
6431043 }
6441044
6451045 char* scroll_statement(){
646- // CURSOR X,Y
1046+ // SCROLL X,Y
6471047 return param2_statement(LIB_SCROLL);
6481048 }
6491049
@@ -662,14 +1062,208 @@
6621062 call_lib_code(LIB_WAIT);
6631063 return 0;
6641064 }
1065+char* var_statement(){
1066+ // Clear flags
1067+ unsigned int flags=0;
1068+ // Prepare stack
1069+ // Note that 12 bytes is used in lib_var()
1070+ // Another 4 bytes is used for return address
1071+ short stack=12;
1072+ char b;
1073+ do {
1074+ // Seek variable
1075+ next_position();
1076+ b=g_source[g_srcpos++];
1077+ if (b<'A' || 'Z'<b) return ERR_SYNTAX;
1078+ flags|=1<<(b-'A');
1079+ stack+=4;
1080+ // Support float and string variables
1081+ b=g_source[g_srcpos];
1082+ if (b=='#' || b=='$') g_srcpos++;
1083+ // Seek ',' or end of statement
1084+ next_position();
1085+ b=g_source[g_srcpos++];
1086+ } while(b==',');
1087+ g_srcpos--;
1088+ // Jump to push routine, first
1089+ check_obj_space(2);
1090+ g_object[g_objpos++]=0x04110007; // bgezal zero,label1
1091+ g_object[g_objpos++]=0x27BD0000|((0-stack)&0xffff); // addiu sp,sp,-xx
1092+ // Process will be here after RETURN statement
1093+ // Pop routine
1094+ check_obj_space(1);
1095+ g_object[g_objpos++]=0x03A02821; // addu a1,sp,zero
1096+ call_lib_code(LIB_VAR_POP);
1097+ // Restore stack and return
1098+ check_obj_space(4);
1099+ g_object[g_objpos++]=0x8FA30000|stack; // lw v1,xx(sp)
1100+ g_object[g_objpos++]=0x00600008; // jr v1
1101+ g_object[g_objpos++]=0x27BD0000|stack; // addiu sp,sp,xx
1102+ // Push rotine
1103+ check_obj_space(4); // label1:
1104+ g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp)
1105+ g_object[g_objpos++]=0x03A02821; // addu a1,sp,zero
1106+ g_object[g_objpos++]=0x3C040000|(flags>>16); // lui a0,XXXX
1107+ g_object[g_objpos++]=0x34840000|(flags&0xffff); // ori a0,a0,XXXX
1108+ call_lib_code(LIB_VAR_PUSH);
1109+ return 0;
1110+}
6651111
1112+char* graphic_statement(enum functions func){
1113+ /*
1114+ PSET X1,Y1[,C]
1115+ LINE X1,Y1,X2,Y2[,C]
1116+ BOXFILL X1,Y1,X2,Y2[,C]
1117+ CIRCLE X1,Y1,R[,C]
1118+ CIRCLEFILL X1,Y1,R[,C]
1119+ GPRINT X1,Y1,C,BC,S$
1120+ PUTBMP X1,Y1,M,N,BMP
1121+ $a0 cotains func (8 bits), X1 (12 bits) and Y1 (12 bits)
1122+ $a1 contains X2/R (12 bits) and Y2 (12 bits)
1123+ $v0 contains C/S$/BMP (32 bits)
1124+ */
1125+ char* err;
1126+ int paramnum;
1127+ switch(func){
1128+ case FUNC_PSET:// X1,Y1[,C]
1129+ case FUNC_GCOLOR:// X1,Y1
1130+ case FUNC_POINT:// X1,Y1
1131+ paramnum=2;
1132+ break;
1133+ case FUNC_CIRCLE:// X1,Y1,R[,C]
1134+ case FUNC_CIRCLEFILL:// X1,Y1,R[,C]
1135+ paramnum=3;
1136+ break;
1137+ case FUNC_LINE:// X1,Y1,X2,Y2[,C]
1138+ case FUNC_BOXFILL:// X1,Y1,X2,Y2[,C]
1139+ paramnum=4;
1140+ break;
1141+ case FUNC_GPRINT:// X1,Y1,C,BC,S$
1142+ case FUNC_PUTBMP:// X1,Y1,M,N,BMP
1143+ paramnum=5;
1144+ break;
1145+ default:
1146+ return ERR_UNKNOWN;
1147+ }
1148+
1149+ next_position();
1150+ if (g_source[g_srcpos]==',') {
1151+ // X1 and Y1 is omitted. Set 0x800 for both.
1152+ check_obj_space(4);
1153+ g_object[g_objpos++]=0x27BDFFF8; // addiu sp,sp,-8
1154+ g_object[g_objpos++]=0x3C020080; // lui v0,0x0080
1155+ g_object[g_objpos++]=0x34420800; // ori v0,v0,0x0800
1156+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
1157+ } else {
1158+ // X1
1159+ err=get_value();
1160+ if (err) return err;
1161+ check_obj_space(4);
1162+ g_object[g_objpos++]=0x27BDFFF8; // addiu sp,sp,-8
1163+ g_object[g_objpos++]=0x30420FFF; // andi v0,v0,0xfff
1164+ g_object[g_objpos++]=0x00021300; // sll v0,v0,0xc
1165+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
1166+ // Y1
1167+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1168+ g_srcpos++;
1169+ err=get_value();
1170+ if (err) return err;
1171+ check_obj_space(4);
1172+ g_object[g_objpos++]=0x30420FFF; // andi v0,v0,0xfff
1173+ g_object[g_objpos++]=0x8FA40004; // lw a0,4(sp)
1174+ g_object[g_objpos++]=0x00441025; // or v0,v0,a0
1175+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
1176+ }
1177+ if (2<paramnum) {
1178+ // X2, R, or M
1179+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1180+ g_srcpos++;
1181+ err=get_value();
1182+ if (err) return err;
1183+ check_obj_space(3);
1184+ g_object[g_objpos++]=0x30420FFF; // andi v0,v0,0xfff
1185+ g_object[g_objpos++]=0x00021300; // sll v0,v0,0xc
1186+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
1187+ if (3<paramnum) {
1188+ // X2, BC, or N
1189+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1190+ g_srcpos++;
1191+ err=get_value();
1192+ if (err) return err;
1193+ check_obj_space(4);
1194+ g_object[g_objpos++]=0x30420FFF; // andi v0,v0,0xfff
1195+ g_object[g_objpos++]=0x8FA40008; // lw a0,8(sp)
1196+ g_object[g_objpos++]=0x00441025; // or v0,v0,a0
1197+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
1198+ }
1199+ }
1200+ if (func==FUNC_GPRINT) {
1201+ // S$
1202+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1203+ g_srcpos++;
1204+ err=get_string();
1205+ if (err) return err;
1206+ } else if (func==FUNC_PUTBMP) {
1207+ // BMP
1208+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1209+ g_srcpos++;
1210+ err=get_label();
1211+ if (g_label && !err) {
1212+ // Label/number is constant.
1213+ // Linker will change following codes later.
1214+ // Note that 0x0814xxxx and 0x0815xxxx are specific codes for these.
1215+ check_obj_space(2);
1216+ g_object[g_objpos++]=0x08140000|((g_label>>16)&0x0000FFFF); // lui v0,xxxx
1217+ g_object[g_objpos++]=0x08150000|(g_label&0x0000FFFF); // ori v0,v0,xxxx
1218+ // Change func to FUNC_PUTBMP2 (label mode).
1219+ func=FUNC_PUTBMP2;
1220+ } else {
1221+ err=get_value();
1222+ if (err) return err;
1223+ }
1224+ } else {
1225+ // [,C]
1226+ if (g_source[g_srcpos]==',') {
1227+ g_srcpos++;
1228+ err=get_value();
1229+ if (err) return err;
1230+ } else {
1231+ // If C is omitted, use -1.
1232+ check_obj_space(1);
1233+ g_object[g_objpos++]=0x2402FFFF; // addiu v0,zero,-1
1234+ }
1235+ }
1236+ // Prepare $a0
1237+ check_obj_space(1);
1238+ g_object[g_objpos++]=0x34040000|(func&0x0ff); // ori a0,zero,xxxx
1239+ g_object[g_objpos++]=0x00042600; // sll a0,a0,0x18
1240+ g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp)
1241+ g_object[g_objpos++]=0x00832025; // or a0,a0,v1
1242+ // Prepare $a1
1243+ g_object[g_objpos++]=0x8FA50008; // lw a1,8(sp)
1244+ // Restore stack pointer
1245+ g_object[g_objpos++]=0x27BD0008; // addiu sp,sp,8
1246+ // Call library
1247+ call_lib_code(LIB_GRAPHIC);
1248+ return 0;
1249+}
1250+#ifdef __DEBUG
1251+ char* debug_statement(){
1252+ call_lib_code(LIB_DEBUG);
1253+ return 0;
1254+ }
1255+#endif
1256+
1257+
6661258 char* statement(void){
6671259 char* err;
6681260 int prevpos;
6691261 next_position();
1262+ // Clear flag for temp area usage.
1263+ g_temp_area_used=0;
6701264 // Initialize stack handler used for value
6711265 g_sdepth=g_maxsdepth=0;
672- if (nextCodeIs("REM ")) {
1266+ if (nextCodeIs("REM")) {
6731267 err=rem_statement();
6741268 } else if (nextCodeIs("SOUND ")) {
6751269 err=sound_statement();
@@ -680,17 +1274,25 @@
6801274 } else if (nextCodeIs("CURSOR ")) {
6811275 err=cursor_statement();
6821276 } else if (nextCodeIs("PALETTE ")) {
683- err=palette_statement();
1277+ err=palette_statement(LIB_PALETTE);
1278+ } else if (nextCodeIs("GPALETTE ")) {
1279+ err=palette_statement(LIB_GPALETTE);
6841280 } else if (nextCodeIs("BGCOLOR ")) {
6851281 err=bgcolor_statement();
6861282 } else if (nextCodeIs("CLS")) {
6871283 err=cls_statement();
1284+ } else if (nextCodeIs("GCLS")) {
1285+ err=gcls_statement();
6881286 } else if (nextCodeIs("COLOR ")) {
6891287 err=color_statement();
1288+ } else if (nextCodeIs("GCOLOR ")) {
1289+ err=gcolor_statement();
6901290 } else if (nextCodeIs("RESTORE ")) {
6911291 err=restore_statement();
6921292 } else if (nextCodeIs("DATA ")) {
6931293 err=data_statement();
1294+ } else if (nextCodeIs("CDATA ")) {
1295+ err=cdata_statement();
6941296 } else if (nextCodeIs("LABEL ")) {
6951297 err=label_statement();
6961298 } else if (nextCodeIs("DIM ")) {
@@ -701,6 +1303,12 @@
7011303 err=print_statement();
7021304 } else if (nextCodeIs("IF ")) {
7031305 err=if_statement();
1306+ } else if (nextCodeIs("ELSEIF ")) {
1307+ err=elseif_statement();
1308+ } else if (nextCodeIs("ELSE")) {
1309+ err=else_statement();
1310+ } else if (nextCodeIs("ENDIF")) {
1311+ err=endif_statement();
7041312 } else if (nextCodeIs("END")) {
7051313 err=end_statement();
7061314 } else if (nextCodeIs("EXEC ")) {
@@ -727,6 +1335,42 @@
7271335 err=scroll_statement();
7281336 } else if (nextCodeIs("WAIT ")) {
7291337 err=wait_statement();
1338+ } else if (nextCodeIs("USEGRAPHIC")) {
1339+ err=usegraphic_statement();
1340+ } else if (nextCodeIs("PSET ")) {
1341+ err=graphic_statement(FUNC_PSET);
1342+ } else if (nextCodeIs("LINE ")) {
1343+ err=graphic_statement(FUNC_LINE);
1344+ } else if (nextCodeIs("BOXFILL ")) {
1345+ err=graphic_statement(FUNC_BOXFILL);
1346+ } else if (nextCodeIs("CIRCLE ")) {
1347+ err=graphic_statement(FUNC_CIRCLE);
1348+ } else if (nextCodeIs("CIRCLEFILL ")) {
1349+ err=graphic_statement(FUNC_CIRCLEFILL);
1350+ } else if (nextCodeIs("GPRINT ")) {
1351+ err=graphic_statement(FUNC_GPRINT);
1352+ } else if (nextCodeIs("PUTBMP ")) {
1353+ err=graphic_statement(FUNC_PUTBMP);
1354+ } else if (nextCodeIs("POINT ")) {
1355+ err=graphic_statement(FUNC_POINT);
1356+ } else if (nextCodeIs("VAR ")) {
1357+ err=var_statement();
1358+ } else if (nextCodeIs("DO")) {
1359+ err=do_statement();
1360+ } else if (nextCodeIs("LOOP")) {
1361+ err=loop_statement();
1362+ } else if (nextCodeIs("WHILE ")) {
1363+ err=while_statement();
1364+ } else if (nextCodeIs("WEND")) {
1365+ err=wend_statement();
1366+ } else if (nextCodeIs("BREAK")) {
1367+ err=break_statement();
1368+ } else if (nextCodeIs("SYSTEM")) {
1369+ err=system_statement();
1370+#ifdef __DEBUG
1371+ } else if (nextCodeIs("DEBUG")) {
1372+ err=debug_statement();
1373+#endif
7301374 } else {
7311375 err=let_statement();
7321376 }
@@ -733,5 +1377,11 @@
7331377 if (err) return err;
7341378 // Stack handler must be zero here.
7351379 if (g_sdepth!=0) return ERR_UNKNOWN;
1380+ // Check if temp area is used
1381+ if (g_temp_area_used) {
1382+ // Temp area is used. Insert a garbage collection flag setting routine.
1383+ check_obj_space(1);
1384+ g_object[g_objpos++]=0x7ED6F000;// ext s6,s6,0,31
1385+ }
7361386 return 0;
7371387 }
--- mips/trunk/float.c (nonexistent)
+++ mips/trunk/float.c (revision 149)
@@ -0,0 +1,150 @@
1+#include "./compiler.h"
2+#include "stdlib.h"
3+
4+char* get_float_sub(int pr);
5+
6+char* get_simple_float(void){
7+ int i;
8+ float f;
9+ char* err;
10+ char b1,b2,b3;
11+ next_position();
12+ b1=g_source[g_srcpos];
13+ if (b1=='(') {
14+ // (...)
15+ // Parenthesis
16+ g_srcpos++;
17+ next_position();
18+ err=get_float_sub(priority(OP_VOID));
19+ if (err) return err;
20+ next_position();
21+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
22+ g_srcpos++;
23+ } else if (b1=='-') {
24+ // Unary '-' operator
25+ // Note that unary operators ( + and - ) have higher priority than the other operators
26+ g_srcpos++;
27+ err=get_simple_float();
28+ if (err) return err;
29+ check_obj_space(2);
30+ g_object[g_objpos++]=0x3404; // ori a0,zero,0x123
31+ g_object[g_objpos++]=0x34050000|(OP_SUB&0x0000FFFF); // ori a1,zero,xxxx
32+ call_lib_code(LIB_FLOAT);
33+ } else {
34+ // Main routine of getting float value here
35+ if (b1=='+') g_srcpos++; // Ignore unary '+' operator
36+ next_position();
37+ b1=g_source[g_srcpos];
38+ b2=g_source[g_srcpos+1];
39+ b3=g_source[g_srcpos+2];
40+ if ('0'<=b1 && b1<='9') {
41+ f=strtof((const char*)&g_source[g_srcpos],&err);
42+ if (&g_source[g_srcpos]==err) return ERR_SYNTAX;
43+ g_srcpos=err-g_source;
44+ i=((int*)(&f))[0];
45+ if (i&0xFFFF0000) {
46+ // 32 bit
47+ check_obj_space(2);
48+ g_object[g_objpos++]=0x3C020000|((i>>16)&0x0000FFFF); // lui v0,xxxx
49+ g_object[g_objpos++]=0x34420000|(i&0x0000FFFF); // ori v0,v0,xxxx
50+ } else {
51+ // 16 bit
52+ check_obj_space(1);
53+ g_object[g_objpos++]=0x34020000|(i&0x0000FFFF); // ori v0,zero,xxxx
54+ }
55+ } else {
56+ if ('A'<=b1 && b1<='Z' && b2=='#' && b3=='(') {
57+ // A( - Z(
58+ // Dimension
59+ g_srcpos++;
60+ g_srcpos++;
61+ g_srcpos++;
62+ return get_dim_value(b1);
63+ } else if ('A'<=b1 && b1<='Z' && b2=='#') {
64+ // A-Z
65+ // Simple value
66+ g_srcpos++;
67+ g_srcpos++;
68+ check_obj_space(1);
69+ g_object[g_objpos++]=0x8FC20000|((b1-'A')*4); // lw v0,xx(s8)
70+ } else if ('A'<=b1 && b1<='Z') {
71+ // Starts with A-Z
72+ // Functions
73+ return float_function();
74+ } else {
75+ return ERR_SYNTAX;
76+ }
77+ }
78+ }
79+ // No error
80+ return 0;
81+}
82+
83+char* get_float_sub(int pr){
84+ char* err;
85+ enum operator op;
86+ char b1,b2,b3;
87+ int prevpos;
88+ // Get a value in $v0.
89+ err=get_simple_float();
90+ if (err) return err;
91+ while(1){
92+ // Get the operator in op. If not valid operator, simply return without error.
93+ prevpos=g_srcpos;
94+ err=get_floatOperator();
95+ if (err) return 0;
96+ op=g_last_op;
97+ // Compair current and previous operators.
98+ // If the previous operator has higher priolity, return.
99+ if (pr>=priority(op)) {
100+ g_srcpos=prevpos;
101+ return 0;
102+ }
103+ // Store $v0 in stack
104+ g_sdepth+=4;
105+ if (g_maxsdepth<g_sdepth) g_maxsdepth=g_sdepth;
106+ check_obj_space(1);
107+ g_object[g_objpos++]=0xAFA20000|g_sdepth; // sw v0,xx(sp)
108+ // Get next value.
109+ err=get_float_sub(priority(op));
110+ if (err) return err;
111+ // Get value from stack to $a0.
112+ check_obj_space(1);
113+ g_object[g_objpos++]=0x8FA40000|g_sdepth; // lw a0,xx(sp)
114+ g_sdepth-=4;
115+ // Calculation. Result will be in $v0.
116+ err=calculation_float(op);
117+ if (err) return err;
118+ }
119+}
120+
121+char* get_float(){
122+ // Note that this can be called recursively.
123+ // Value may contain function with a parameter of another value.
124+ char* err;
125+ int prevpos;
126+ if (g_sdepth==0) {
127+ // Initialize stack handler
128+ g_maxsdepth=0;
129+ prevpos=g_objpos;
130+ // Stack decrement command will be filled later
131+ check_obj_space(1);
132+ g_objpos++;
133+ }
134+ err=get_float_sub(priority(OP_VOID));
135+ if (err) return err;
136+ if (g_sdepth==0) {
137+ if (g_maxsdepth==0) {
138+ // Stack was not used.
139+ shift_obj(&g_object[prevpos+1],&g_object[prevpos],g_objpos-prevpos-1);
140+ g_objpos--;
141+ } else {
142+ // Stack was used.
143+ check_obj_space(1);
144+ g_object[prevpos]=0x27BD0000 | (0-g_maxsdepth) & 0x0000FFFF; // addiu sp,sp,-xx
145+ g_object[g_objpos++]=0x27BD0000 | g_maxsdepth & 0x0000FFFF; // addiu sp,sp,xx
146+ }
147+ }
148+ g_lastvar=VAR_FLOAT;
149+ return 0;
150+}
\ No newline at end of file
--- mips/trunk/memory.c (revision 148)
+++ mips/trunk/memory.c (revision 149)
@@ -8,15 +8,19 @@
88 #include "compiler.h"
99
1010 /*
11- ALLOC_VAR_NUM: # of variables used for allocation of memory (string/dimension).
12- 0 is for A, 1 is for B, ... , and 25 is for Z.
13- This number also includes temporary area used for string construction etc.
14- Temporary area is cleared every line of BASIC code in alloc_memory().
15- ALLOC_BLOCK_NUM: # of blocks that can be used for memory allocation.
16- This # also includes the ones for ALLOC_VAR_NUM.
17- After ALLOC_VAR_NUM area, dedicated memory area information follows.
18- Currently, only PCG is used in this block.
19- Therefore, ALLOC_VAR_NUM+1 == ALLOC_BLOCK_NUM
11+ ALLOC_VAR_NUM: # of variables used for allocation of memory (string/dimension).
12+ 0 is for A, 1 is for B, ... , and 25 is for Z.
13+ This number also includes temporary area used for string construction etc.
14+ Temporary area is cleared every line of BASIC code in alloc_memory().
15+ ALLOC_BLOCK_NUM: # of blocks that can be used for memory allocation.
16+ This # also includes the ones for ALLOC_VAR_NUM.
17+ After ALLOC_VAR_NUM area, dedicated memory area and permanent area follows.
18+ Currently, only PCG is used for permanent pourpose.
19+ 10 permanant blocks can be used.
20+ Therefore, ALLOC_VAR_NUM+11 == ALLOC_BLOCK_NUM
21+ ALLOC_PERM_BLOCK: Start # of permanent blocks.
22+ The blocks after this number is permanently stored.
23+ Therefore, it must be released when it's not used any more.
2024 */
2125
2226 void set_free_area(void* begin, void* end){
@@ -46,7 +50,8 @@
4650 asm volatile("bltz $s6,_alloc_memory_main"); // Skip if $s6<0
4751 // Following code will be activated after setting $s6 register
4852 // every line and after label statement.
49- asm volatile("subu $s6,$zero,$s6"); // $s6=0-$s6
53+ asm volatile("lui $v0,0x8000");
54+ asm volatile("or $s6,$v0,$s6"); // $s6=0x80000000|$s6;
5055 // Remove all temporary blocks
5156 // Note that g_var_size is short integer.
5257 // Note that ALLOC_VAR_NUM is used here (but not ALLOC_BLOC_NUM)
@@ -61,7 +66,7 @@
6166 asm volatile("b _alloc_memory_main");
6267 }
6368 void* _alloc_memory_main(int size, int var_num){
64- int i,j,candidate,after_this;
69+ int i,j,candidate;
6570 // Assign temp var number
6671 if (var_num<0) {
6772 // Use ALLOC_VAR_NUM here but not ALLOC_BLOCK_NUM
@@ -76,6 +81,9 @@
7681 return 0;
7782 }
7883 }
84+ // Clear var to be assigned.
85+ g_var_size[var_num]=0;
86+ g_var_pointer[var_num]=0;
7987 while(1){
8088 // Try the block after last block
8189 candidate=0;
@@ -87,26 +95,24 @@
8795 }
8896 if (candidate+size<=g_max_mem) break;
8997 // Check between blocks
90- candidate=-1;
98+ // Note that there is at least one block with zero pointer and zero size (see above).
9199 for(i=0;i<ALLOC_BLOCK_NUM;i++){
92- after_this=g_max_mem;
100+ // Candidate is after this block.
101+ candidate=g_var_pointer[i]+g_var_size[i];
102+ // Check if there is an overlap.
93103 for(j=0;j<ALLOC_BLOCK_NUM;j++){
94- if (g_var_pointer[i]<g_var_pointer[j] && g_var_pointer[j]<after_this) {
95- after_this=g_var_pointer[j];
96- }
104+ if (g_var_size[j]==0) continue;
105+ if (candidate+size<=g_var_pointer[j]) continue;
106+ if (g_var_pointer[j]+g_var_size[j]<=candidate) continue;
107+ // This block overlaps with the candidate
108+ candidate=-1;
109+ break;
97110 }
98- if (g_var_pointer[i]+g_var_size[i]+size<=after_this) {
99- // Possible block found.
100- candidate=g_var_pointer[i]+g_var_size[i];
101- // Check if this area is not used by others.
102- for(j=0;j<ALLOC_BLOCK_NUM;j++){
103- if (candidate+size<g_var_pointer[j]) continue;
104- if (g_var_pointer[j]+g_var_size[j]<=candidate) continue;
105- // This block is at least partly taken by another block.
106- candidate=-1;
107- break;
108- }
109- if (0<=candidate) break;
111+ if (0<=candidate && candidate+size<=g_max_mem) {
112+ // Available block found
113+ break;
114+ } else {
115+ candidate=-1;
110116 }
111117 }
112118 if (0<=candidate) break;
@@ -132,4 +138,38 @@
132138 break;
133139 }
134140 }
141+}
142+
143+void move_to_perm_block(int var_num){
144+ int i;
145+ // Find available permanent block
146+ for (i=ALLOC_PERM_BLOCK;i<ALLOC_BLOCK_NUM;i++){
147+ if (g_var_size[i]==0) break;
148+ }
149+ if (ALLOC_BLOCK_NUM<=i) err_no_block(); // Not found
150+ // Available block found.
151+ // Copy value from variable.
152+ g_var_size[i]=g_var_size[var_num];
153+ g_var_pointer[i]=g_var_pointer[var_num];
154+ g_var_mem[i]=g_var_mem[var_num];
155+ // Clear variable
156+ g_var_size[var_num]=0;
157+ g_var_mem[var_num]=0;
158+}
159+
160+void move_from_perm_block(int var_num){
161+ int i,pointer;
162+ pointer=(int)g_var_mem[var_num]-(int)g_heap_mem;
163+ pointer>>=2;
164+ // Find stored block
165+ for (i=ALLOC_PERM_BLOCK;i<ALLOC_BLOCK_NUM;i++){
166+ if (0<g_var_size[i] && g_var_pointer[i]==pointer) break;
167+ }
168+ if (ALLOC_BLOCK_NUM<=i) err_unknown(); // Not found
169+ // Stored block found.
170+ // Replace pointer
171+ g_var_size[var_num]=g_var_size[i];
172+ g_var_pointer[var_num]=g_var_pointer[i];
173+ // Clear block
174+ g_var_size[i]=0;
135175 }
\ No newline at end of file
--- mips/trunk/keyinput.c (revision 148)
+++ mips/trunk/keyinput.c (revision 149)
@@ -6,7 +6,7 @@
66 // キー入力、カーソル表示関連機能 by K.Tanaka
77 // PS/2キーボード入力システム、カラーテキスト出力システム利用
88
9-#include "colortext32.h"
9+#include "videoout.h"
1010 #include "ps2keyboard.h"
1111 #include "keyinput.h"
1212
--- mips/trunk/compiler.c (revision 148)
+++ mips/trunk/compiler.c (revision 149)
@@ -80,6 +80,11 @@
8080 int len;
8181 for(len=0;str[len];len++);
8282 if (!strncmp(g_source+g_srcpos,str,len)) {
83+ if ('A'<=str[len-1] && str[len-1]<='Z') {
84+ // When the last character of str is alphabet,
85+ // the next character in source must be space, enter, or ':'.
86+ if (0x20<g_source[g_srcpos+len] && g_source[g_srcpos+len]!=':') return 0;
87+ }
8388 // String matches in the current position in source.
8489 g_srcpos+=len;
8590 return len;
@@ -97,7 +102,14 @@
97102 // Check if line number exists
98103 next_position();
99104 b1=g_source[g_srcpos];
100- if ('0'<=b1 && b1<='9') {
105+ if (b1<0x20) {
106+ // The end of line.
107+ // Don't add $s6-setting command.
108+ if (g_source[g_srcpos]==0x0D && g_source[g_srcpos+1]==0x0A) g_srcpos++;
109+ g_srcpos++;
110+ return 0;
111+ } else if ('0'<=b1 && b1<='9') {
112+ // Line number exists
101113 err=get_label();
102114 if (err) return err;
103115 g_line=g_label;
--- mips/trunk/api.h (revision 148)
+++ mips/trunk/api.h (revision 149)
@@ -29,6 +29,10 @@
2929 #define size_t unsigned int
3030 #endif
3131
32-#include "colortext32.h"
32+// Used for asm("wait")
33+#define WAIT "wait"
34+
35+#include "videoout.h"
3336 #include "SDFSIO.h"
3437 #include "ps2keyboard.h"
38+#include "debug.h"
--- mips/trunk/compiler.h (revision 148)
+++ mips/trunk/compiler.h (revision 149)
@@ -9,14 +9,28 @@
99 // Number of variables (including temporary ones)
1010 #define ALLOC_VAR_NUM 36
1111 // Number of blocks that can be assigned for memory allocation (including ALLOC_VAR_NUM)
12-#define ALLOC_BLOCK_NUM 37
12+#define ALLOC_BLOCK_NUM 48
1313 // Block # dedicated for PCG
1414 #define ALLOC_PCG_BLOCK 36
15+// Block # dedicated for GRAPHIC
16+#define ALLOC_GRAPHIC_BLOCK 37
17+// Start # of permanent blocks
18+#define ALLOC_PERM_BLOCK 38
1519
20+// Persistent RAM bytes used for object, heap and exception data
21+#define PERSISTENT_RAM_SIZE (1024*56)
22+// Exception data area bytes
23+#define EXCEPTION_DATA_SIZE (64)
1624 // RAM size used for object and heap
17-#define RAMSIZE (1024*25)
25+#define RAMSIZE (PERSISTENT_RAM_SIZE-EXCEPTION_DATA_SIZE)
1826
1927 /* Enums */
28+enum variable{
29+ VAR_INTEGER,
30+ VAR_FLOAT,
31+ VAR_STRING
32+};
33+
2034 enum operator{
2135 OP_VOID=0,
2236 OP_OR =1,
@@ -28,11 +42,13 @@
2842 OP_LTE =7,
2943 OP_MT =8,
3044 OP_MTE =9,
31- OP_ADD =10,
32- OP_SUB =11,
33- OP_MUL =12,
34- OP_DIV =13,
35- OP_REM =14
45+ OP_SHL =10,
46+ OP_SHR =11,
47+ OP_ADD =12,
48+ OP_SUB =13,
49+ OP_MUL =14,
50+ OP_DIV =15,
51+ OP_REM =16
3652 };
3753 enum libs{
3854 LIB_SOUND,
@@ -41,12 +57,16 @@
4157 LIB_SETDRAWCOUNT,
4258 LIB_DRAWCOUNT,
4359 LIB_PALETTE,
60+ LIB_GPALETTE,
4461 LIB_BGCOLOR,
4562 LIB_CURSOR,
4663 LIB_CLS,
64+ LIB_GCLS,
4765 LIB_COLOR,
66+ LIB_GCOLOR,
4867 LIB_KEYS,
4968 LIB_RESTORE,
69+ LIB_RESTORE2,
5070 LIB_READ,
5171 LIB_MIDSTR,
5272 LIB_CLEAR,
@@ -69,13 +89,60 @@
6989 LIB_PCG,
7090 LIB_SCROLL,
7191 LIB_WAIT,
92+ LIB_VAR_PUSH,
93+ LIB_VAR_POP,
94+ LIB_SYSTEM,
95+ LIB_SPRINTF,
96+ LIB_FLOAT,
97+ LIB_FLOATFUNCS,
98+ LIB_CREAD,
99+ LIB_USEGRAPHIC,
100+ LIB_GRAPHIC,
101+ LIB_DEBUG
72102 };
103+enum functions{
104+ FUNC_FLOAT,
105+ FUNC_INT,
106+ FUNC_VALSHARP,
107+ FUNC_SIN,
108+ FUNC_COS,
109+ FUNC_TAN,
110+ FUNC_ASIN,
111+ FUNC_ACOS,
112+ FUNC_ATAN,
113+ FUNC_SINH,
114+ FUNC_COSH,
115+ FUNC_TANH,
116+ FUNC_EXP,
117+ FUNC_LOG,
118+ FUNC_LOG10,
119+ FUNC_POW,
120+ FUNC_SQRT,
121+ FUNC_CEIL,
122+ FUNC_FLOOR,
123+ FUNC_FABS,
124+ FUNC_MODF,
125+ FUNC_FMOD,
126+ FUNC_PSET,
127+ FUNC_LINE,
128+ FUNC_BOXFILL,
129+ FUNC_CIRCLE,
130+ FUNC_CIRCLEFILL,
131+ FUNC_GPRINT,
132+ FUNC_PUTBMP,
133+ FUNC_PUTBMP2,
134+ FUNC_GCOLOR,
135+ FUNC_POINT,
136+};
73137
74-/* Global vars */
138+/* Global vars (see globalvers.c) */
139+extern int g_intconst;
140+extern char g_valueisconst;
75141 extern int g_rnd_seed;
76142 extern unsigned int g_label;
77143 extern int g_sdepth;
78144 extern int g_maxsdepth;
145+extern enum variable g_lastvar;
79146 extern char* g_source;
80147 extern int g_srcpos;
81148 extern int g_line;
@@ -88,14 +155,19 @@
88155 extern enum operator g_last_op;
89156 extern int g_end_addr;
90157 extern int g_gp;
158+extern int g_s6;
91159 extern char RAM[RAMSIZE];
160+extern unsigned int g_ex_data[EXCEPTION_DATA_SIZE/4];
92161 extern int g_var_mem[ALLOC_BLOCK_NUM];
93162 extern unsigned short g_var_pointer[ALLOC_BLOCK_NUM];
94163 extern unsigned short g_var_size[ALLOC_BLOCK_NUM];
164+extern char g_temp_area_used;
95165 extern int* g_heap_mem;
96166 extern int g_max_mem;
97167 extern char g_disable_break;
98168 extern unsigned char* g_pcg_font;
169+extern char g_use_graphic;
170+extern unsigned short* g_graphic_area;
99171
100172 /* Prototypes */
101173 int get_gp(void);
@@ -105,6 +177,11 @@
105177 char* compile_line(void);
106178 int nextCodeIs(char* str);
107179
180+char* init_file(char* buff,char* appname);
181+void close_file();
182+void read_file(int blocklen);
183+char* compile_file();
184+
108185 void err_break(void);
109186 void err_music(char* str);
110187 void err_data_not_found(void);
@@ -114,6 +191,7 @@
114191 void err_div_zero(void);
115192 void err_unkonwn(void);
116193 void err_unexp_next(void);
194+void err_no_block(void);
117195 char* resolve_label(int s6);
118196
119197 void set_sound(unsigned long* data);
@@ -123,15 +201,20 @@
123201
124202 char* statement(void);
125203 char* gosub_statement();
204+char* graphic_statement(enum functions func);
126205
127206 char* function(void);
128207 char* str_function(void);
208+char* float_function(void);
129209
130210 void call_library(void);
211+void reset_dataread();
131212
132213 void free_temp_str(char* str);
133214 void* alloc_memory(int size, int var_num);
134215 void* calloc_memory(int size, int var_num);
216+void move_to_perm_block(int var_num);
217+void move_from_perm_block(int var_num);
135218
136219 char* link(void);
137220 char* get_label(void);
@@ -138,13 +221,24 @@
138221 void* search_label(unsigned int label);
139222
140223 char* get_string();
224+char* simple_string(void);
141225
142226 char* get_operator(void);
227+char* get_floatOperator(void);
143228 char* calculation(enum operator op);
229+char* calculation_float(enum operator op);
230+int lib_float(int ia0,int iv0, enum operator a1);
144231
232+char* get_dim_value(char b1);
145233 char* get_simple_value(void);
146234 char* get_value();
235+char* get_floatOrValue();
236+char* get_stringFloatOrValue();
147237
238+void blue_screen(void);
239+
240+char* get_float();
241+
148242 /* Error messages */
149243 #define ERR_SYNTAX (char*)(g_err_str[0])
150244 #define ERR_NE_BINARY (char*)(g_err_str[1])
@@ -160,6 +254,10 @@
160254 #define ERR_MULTIPLE_LABEL (char*)(g_err_str[11])
161255 #define ERR_BREAK (char*)(g_err_str[12])
162256 #define ERR_UNEXP_NEXT (char*)(g_err_str[13])
257+#define ERR_NO_BLOCK (char*)(g_err_str[14])
258+#define ERR_GOSUB_ASH (char*)(g_err_str[15])
259+#define ERR_INVALID_BREAK (char*)(g_err_str[16])
260+#define ERR_INVALID_ELSEIF (char*)(g_err_str[17])
163261
164262 /* Macros */
165263
@@ -167,27 +265,39 @@
167265 #define next_position() while(g_source[g_srcpos]==' ') {g_srcpos++;}
168266
169267 // Check if object area is not full.
170-#define check_obj_space(x) if (g_objmax<g_object+g_objpos+x) return ERR_NE_BINARY
268+#define check_obj_space(x) if (g_objmax<g_object+g_objpos+(x)) return ERR_NE_BINARY
171269
172270 // Returns priority of operator
173-#define priority(x) (int)g_priority[(int)x]
271+#define priority(x) (int)g_priority[(int)(x)]
174272
175273 // Insert code for calling library
176-//02E0F809 jalr ra,s7
177-//24070000 addiu a3,zero,0000
274+//02E0F809 jalr ra,s7
275+//24070000 addiu a3,zero,0000
178276 #define call_lib_code(x) \
179277 check_obj_space(2);\
180278 g_object[g_objpos++]=0x02E0F809;\
181- g_object[g_objpos++]=0x24070000|(x&0x0000FFFF)
279+ g_object[g_objpos++]=0x24070000|((x)&0x0000FFFF)
182280
183281 // Division macro for unsigned long
184282 // Valid for 31 bits for all cases and 32 bits for some cases
185-#define div32(x,y,z) ((((unsigned long long)((unsigned long)x))*((unsigned long long)((unsigned long)y)))>>z)
283+#define div32(x,y,z) ((((unsigned long long)((unsigned long)(x)))*((unsigned long long)((unsigned long)(y))))>>(z))
186284
187285 // Divide by 10 (valid for 32 bits)
188286 #define div10_32(x) div32(x,0xcccccccd,35)
189-#define rem10_32(x) (x-10*div10_32(x))
287+#define rem10_32(x) ((x)-10*div10_32(x))
190288
191289 // Divide by 36 (valid for 32 bits)
192290 #define div36_32(x) div32(x,0xe38e38e4,37)
193291 #define rem36_32(x) (x-36*div36_32(x))
292+
293+// Check break key or buttons when executing BASIC code.
294+// In PS/2 mode, detect ctrl-break.
295+// In button mode, detect pushing four buttons are pushed simultaneously.
296+#define check_break() \
297+ if (g_disable_break==0) {\
298+ if (inPS2MODE()) {\
299+ if (ps2keystatus[0x03]) err_break();\
300+ } else {\
301+ if ((PORTB&0x4c80)==0) err_break();\
302+ }\
303+ }
--- mips/trunk/file.c (revision 148)
+++ mips/trunk/file.c (revision 149)
@@ -1,8 +1,8 @@
11 /*
22 This file is provided under the LGPL license ver 2.1.
3- Written by Katsumi.
3+ Written by K.Tanaka & Katsumi
4+ http://www.ze.em-net.ne.jp/~kenken/index.html
45 http://hp.vector.co.jp/authors/VA016157/
5- kmorimatsu@users.sourceforge.jp
66 */
77
88 #include <xc.h>
@@ -9,14 +9,15 @@
99 #include "api.h"
1010 #include "compiler.h"
1111
12-FSFILE* g_fhandle;
13-char* g_fbuff;
12+static FSFILE* g_fhandle;
13+static char* g_fbuff;
14+static int g_size;
1415
15-int init_file(char* buff,char* appname){
16+char* init_file(char* buff,char* appname){
1617 // Open file
1718 g_fhandle=FSfopen(appname,"r");
1819 if (!g_fhandle) {
19- return -1;
20+ return ERR_UNKNOWN;
2021 }
2122 g_fbuff=buff;
2223 g_line=0;
@@ -24,45 +25,70 @@
2425 return 0;
2526 }
2627
27-char* compile_file(){
28- int i,size;
29- int in_string;
30- char* err;
31-
32- in_string=0;
28+void close_file(){
29+ FSfclose(g_fhandle);
30+}
3331
34- // Read first 512 bytes (all uppercase).
35- size=FSfread((void*)&g_fbuff[0],1,512,g_fhandle);
36- for(i=0;i<512;i++){
37- if ('a'<=g_fbuff[i] && g_fbuff[i]<='z' && !in_string) g_fbuff[i]+='A'-'a';
38- if (g_fbuff[i]=='"') in_string=1-in_string;
39- if (g_fbuff[i]==0x0a || g_fbuff[i]==0x0d) in_string=0;
40- }
41- while (size==512) {
42- while(g_srcpos<256){
43- err=compile_line();
44- if (err) return err;
45- }
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 {
4644 // Shift buffer and source position 256 bytes.
4745 for(i=0;i<256;i++) g_fbuff[i]=g_fbuff[i+256];
4846 g_srcpos-=256;
49- // Read next 256 line (all uppercase).
50- size=256+FSfread((void*)&g_fbuff[256],1,256,g_fhandle);
51- for(i=256;i<512;i++){
52- if ('a'<=g_fbuff[i] && g_fbuff[i]<='z' && !in_string) g_fbuff[i]+='A'-'a';
53- if (g_fbuff[i]=='"') in_string=1-in_string;
54- if (g_fbuff[i]==0x0a || g_fbuff[i]==0x0d) in_string=0;
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]=' ';
5565 }
66+ if (g_fbuff[i]==0x0a || g_fbuff[i]==0x0d) in_string=escape=0;
5667 }
57- // Null charcter at the end
58- g_source[size]=0x00;
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;
5985 // Compile last few lines.
60- while(g_srcpos<size-1){
86+ while(g_srcpos<g_size-1){
6187 err=compile_line();
6288 if (err) return err;
6389 }
64- // Add "END" statement.
65- g_source="END\n";
90+ // Add "DATA 0" and "END" statements.
91+ g_source="DATA 0:END\n";
6692 g_srcpos=0;
6793 err=compile_line();
6894 if (err) return err;
--- mips/trunk/main.c (revision 148)
+++ mips/trunk/main.c (revision 149)
@@ -1,12 +1,13 @@
11 /*
22 This file is provided under the LGPL license ver 2.1.
3- Written by K.Tanaka
3+ Written by K.Tanaka & Katsumi
44 http://www.ze.em-net.ne.jp/~kenken/index.html
5+ http://hp.vector.co.jp/authors/VA016157/
56 */
67
78 // main.c
8-// MachiKania BASIC System
9-// KM-BASIC 統合開発実行環境 for PIC32MX150F128B / PIC32MX250F128B by K.Tanaka
9+// MachiKania BASIC System Ver Zoea
10+// KM-BASIC 統合開発実行環境 for PIC32MX170F256B / PIC32MX270F256B by K.Tanaka
1011
1112 // 利用システム
1213 // ps2keyboard.X.a : PS/2キーボード入力システムライブラリ
@@ -13,15 +14,12 @@
1314 // lib_colortext32.a : カラービデオ信号出力システムライブラリ(30×27テキスト版)
1415 // libsdfsio.a : SDカードアクセス用ライブラリ
1516
16-#define SYSVER1 "Nauplia"
17-#define SYSVER2 "1.01"
18-#define BASVER "KM-1120"
19-
2017 #include <xc.h>
2118 #include "api.h"
2219 #include "compiler.h"
2320 #include "editor.h"
2421 #include "keyinput.h"
22+#include "main.h"
2523
2624 //外付けクリスタル with PLL (16倍)
2725 #pragma config PMDL1WAY = OFF, IOL1WAY = OFF
@@ -28,13 +26,12 @@
2826 #pragma config FPLLIDIV = DIV_1, FPLLMUL = MUL_16, FPLLODIV = DIV_1
2927 #pragma config FNOSC = PRIPLL, FSOSCEN = OFF, POSCMOD = XT, OSCIOFNC = OFF
3028 #pragma config FPBDIV = DIV_1, FWDTEN = OFF, JTAGEN = OFF, ICESEL = ICS_PGx1
29+#pragma config FCKSM = CSECMD
3130
3231 #define mBMXSetRAMKernProgOffset(offset) (BMXDKPBA = (offset))
3332 #define mBMXSetRAMUserDataOffset(offset) (BMXDUDBA = (offset))
3433 #define mBMXSetRAMUserProgOffset(offset) (BMXDUPBA = (offset))
3534
36-#define FILENAME_FLASH_ADDRESS 0x9D005800
37-
3835 // INIファイル指定キーワード(8文字以内)
3936 const char InitKeywords[][9]={
4037 "106KEY","101KEY","NUMLOCK","CAPSLOCK","SCRLLOCK"
@@ -122,9 +119,31 @@
122119 }
123120 FSfclose(fp);
124121 }
122+
123+void printhex8(unsigned char d){
124+ printchar("0123456789ABCDEF"[d>>4]);
125+ printchar("0123456789ABCDEF"[d&0x0f]);
126+}
127+
128+void printhex16(unsigned short d){
129+ printhex8(d>>8);
130+ printhex8(d&0x00ff);
131+}
132+
133+void printhex32(unsigned int d){
134+ printhex16(d>>16);
135+ printhex16(d&0x0000ffff);
136+}
137+
125138 int main(void){
126139 char *appname,*s;
127140
141+ if(DEVCFG1 & 0x8000){
142+ // Set Clock switching enabled and reset
143+ NVMWriteWord(&DEVCFG1,DEVCFG1 & 0xffff7fff);
144+ SoftReset();
145+ }
146+
128147 /* ポートの初期設定 */
129148 TRISA = 0x0000; // PORTA全て出力
130149 ANSELA = 0x0000; // 全てデジタル
@@ -138,14 +157,17 @@
138157 RPB5R=4; //RPB5:SDO2
139158
140159 // Make RAM executable. See also "char RAM[RAMSIZE]" in globalvars.c
141- mBMXSetRAMKernProgOffset(0x8000-RAMSIZE);
142- mBMXSetRAMUserDataOffset(0x8000);
143- mBMXSetRAMUserProgOffset(0x8000);
160+ mBMXSetRAMKernProgOffset(PIC32MX_RAMSIZE-RAMSIZE);
161+ mBMXSetRAMUserDataOffset(PIC32MX_RAMSIZE);
162+ mBMXSetRAMUserProgOffset(PIC32MX_RAMSIZE);
144163
145164 ps2mode(); //RA1オン(PS/2有効化マクロ)
146165 init_composite(); // ビデオメモリクリア、割り込み初期化、カラービデオ出力開始
147166 setcursor(0,0,COLOR_NORMALTEXT);
148167
168+ // Show blue screen if exception before soft reset.
169+ blue_screen();
170+
149171 printstr("MachiKania BASIC System\n");
150172 printstr(" Ver "SYSVER1" "SYSVER2" by KENKEN\n");
151173 printstr("BASIC Compiler "BASVER"\n");
@@ -154,7 +176,7 @@
154176 setcursorcolor(COLOR_NORMALTEXT);
155177 printstr("Init File System...");
156178 // Initialize the File System
157- if(FSInit()==NULL){ //ファイルシステム初期化
179+ if(FSInit()==FALSE){ //ファイルシステム初期化
158180 //エラーの場合停止
159181 setcursorcolor(COLOR_ERRORTEXT);
160182 printstr("\nFile System Error\n");
@@ -190,5 +212,5 @@
190212 // buttonmode(); //ボタン有効化
191213 g_disable_break=1; // Breakキー無効化
192214 runbasic(tempfile,0);
193- while(1) asm("wait");
215+ while(1) asm(WAIT);
194216 }
--- mips/trunk/linker.c (revision 148)
+++ mips/trunk/linker.c (revision 149)
@@ -60,8 +60,8 @@
6060 g_srcpos++;
6161 b1=g_source[g_srcpos];
6262 } while ('0'<= b1 && b1<='9' || 'A'<=b1 && b1<='Z');
63- // Length of the label must be less than 7.
64- if (6<g_srcpos-prevpos) {
63+ // Length of the label must be between 2 and 6.
64+ if (g_srcpos-prevpos<2 || 6<g_srcpos-prevpos) {
6565 g_srcpos=prevpos;
6666 return ERR_LABEL_LONG;
6767 }
@@ -122,20 +122,114 @@
122122 }
123123 }
124124
125+void* search_breakout(unsigned int start){
126+ unsigned int pos,code1,depth;
127+ // Start search from start point where BREAK statement is used.
128+ depth=0;
129+ for(pos=start;pos<g_objpos;pos++){
130+ code1=g_object[pos];
131+ switch(code1>>16){
132+ case 0x0411:
133+ // "bgezal zero," assembly found. Skip following block (strig).
134+ pos+=code1&0x0000FFFF;
135+ pos--;
136+ break;
137+ case 0x0820: // FOR
138+ case 0x0821: // WHILE
139+ case 0x0822: // DO
140+ depth++;
141+ break;
142+ case 0x0830: // NEXT
143+ case 0x0831: // WEND
144+ case 0x0832: // LOOP
145+ if (0<depth) {
146+ depth--;
147+ break;
148+ }
149+ // Destination found.
150+ return (void*)&g_object[pos];
151+ default:
152+ break;
153+ }
154+ }
155+ return 0;
156+}
157+
158+void* search_ifout(unsigned int start){
159+ unsigned int pos,code1,depth;
160+ // Start search from start point where BREAK statement is used.
161+ depth=0;
162+ for(pos=start;pos<g_objpos;pos++){
163+ code1=g_object[pos];
164+ switch(code1>>16){
165+ case 0x0411:
166+ // "bgezal zero," assembly found. Skip following block (strig).
167+ pos+=code1&0x0000FFFF;
168+ pos--;
169+ break;
170+ case 0x3000: // Block marker
171+ if (code1&0x00008000) {
172+ // end block
173+ if (0<depth) {
174+ depth--;
175+ break;
176+ }
177+ // Destination found.
178+ return (void*)&g_object[pos];
179+ } else {
180+ // begin block
181+ depth++;
182+ }
183+ default:
184+ break;
185+ }
186+ }
187+ return 0;
188+}
189+
125190 /*
126191 Following codes are dedicated to specific use:
127192 0x0810xxxx, 0x0811xxxx: GOTO statement
128193 0x0812xxxx, 0x0813xxxx: GOSUB statement
129194 0x0814xxxx, 0x0815xxxx: SOUND etc, for setting v0 as pointer to DATA array.
195+ 0x0816xxxx: BREAK statemant and relatives
196+ 0x08160000: BREAK
197+ 0x08160100: Jump to next ELSE, ELSEIF or ENDIF
198+ 0x082xyyyy: Begin block (FOR/DO/WHILE)
199+ 0x083xyyyy: End block (NEXT/LOOP/WEND)
200+ 0x00000020, 0x00000021,
201+ 0x00000022, 0x00000023: Marker for begining the DATA region.
202+ MLB 2 bits show skip byte length in DATA.
203+ 0x30000000: Begin block (IF-THEN-ELSEIF-ELSE-ENDIF)
204+ 0x30008000: End block (IF-THEN-ELSEIF-ELSE-ENDIF)
205+
206+ IF-THEN-ELSEIF-ELSE-ENDIF is written as follows:
207+ IF-THEN: 0x30000000 0x10400000 0x30000000
208+ ELSEIF-THEN: 0x08160100 0x30008000 (conditional expression) 0x10400000 0x30000000
209+ ELSE: 0x08160100 0x30008000 0x30000000
210+ ENDIF: 0x30008000 0x30008000
211+ , where "0x10400000 0x30000000" and "0x08160100 0x30008000" will be replaced by
212+ codes jumping to next 0x30008000. The 0x30000000 - 0x30008000 blocks will be skipped.
130213 */
131214
132215 char* link(void){
133216 int pos;
134217 unsigned int code1,code2,label;
218+ g_fileline=0;
135219 for(pos=0;pos<g_objpos;pos++){
136220 code1=g_object[pos];
137- switch(code1&0xFFFF0000){
138- case 0x08100000:
221+ switch(code1>>16){
222+ case 0x0411:
223+ // "bgezal zero," assembly found. Skip following block (strig).
224+ pos+=code1&0x0000FFFF;
225+ pos--;
226+ break;
227+ case 0x3416:
228+ // "ori s6,zero,xxxx" found this is the first word in a line.
229+ g_fileline++;
230+ g_line=code1&0x0000FFFF;
231+ break;
232+ case 0x0810:
139233 // GOTO
140234 code2=g_object[pos+1];
141235 if ((code2&0xFFFF0000)!=0x08110000) continue;
@@ -151,7 +245,7 @@
151245 g_object[pos++]=code1;
152246 g_object[pos]=0x00000000; // nop
153247 break;
154- case 0x08120000:
248+ case 0x0812:
155249 // GOSUB
156250 code2=g_object[pos+1];
157251 if ((code2&0xFFFF0000)!=0x08130000) continue;
@@ -167,19 +261,105 @@
167261 g_object[pos++]=0x00000000; // nop
168262 g_object[pos]=code2;
169263 break;
170- case 0x08140000:
264+ case 0x0814:
171265 // SOUND etc, for setting v0 as pointer to label/line
172266 code2=g_object[pos+1];
173267 if ((code2&0xFFFF0000)!=0x08150000) continue;
174268 code1&=0x0000FFFF;
175269 code2&=0x0000FFFF;
176- g_label=label;
177270 label=(code1<<16)|code2;
178271 code1=(int)search_label(label);
272+ g_label=label;
179273 if (!code1) return ERR_LABEL_NF;
180274 g_object[pos++]=0x3C020000|((code1>>16)&0x0000FFFF); // lui v0,xxxx
181275 g_object[pos] =0x34420000|(code1&0x0000FFFF); // ori v0,v0,xxxx
182276 break;
277+ case 0x0816:
278+ switch(code1&0xFFFF) {
279+ case 0x0000:
280+ // BREAK statement
281+ // Find next the NEXT or WHILE statement and insert jump code after this.
282+ g_label=g_line;
283+ code1=(int)search_breakout(pos);
284+ if (!code1) return ERR_INVALID_BREAK;
285+ code1&=0x0FFFFFFF;
286+ code1>>=2;
287+ code1|=0x08000000; // j xxxx
288+ g_object[pos]=code1;
289+ break;
290+ case 0x0100:
291+ // Jump to next ENDIF
292+ g_label=g_line;
293+ // "pos+2" is for skipping next code (must be 0x30008000)
294+ code1=(int)search_ifout(pos+2);
295+ if (!code1) return ERR_INVALID_ELSEIF;
296+ code1&=0x0FFFFFFF;
297+ code1>>=2;
298+ code1|=0x08000000; // j xxxx
299+ g_object[pos]=code1;
300+ break;
301+ default:
302+ break;
303+ }
304+ break;
305+ case 0x3000:
306+ // Block marker
307+ switch(code1&0xFFFF) {
308+ case 0x0000:
309+ // Begin if block
310+ if (g_object[pos-1]==0x10400000) { // beq v0,zero,xxxx
311+ // IF-THEN or ELSEIF-THEN
312+ // Jump to next ELSE, ELSEIF or ENDIF
313+ g_label=g_line;
314+ // "pos+1" is for skipping current code (0x30000000)
315+ code1=(int)search_ifout(pos+1);
316+ if (!code1) return ERR_INVALID_ELSEIF;
317+ code1-=(int)(&g_object[pos]);
318+ code1>>=2;
319+ code1&=0x0000FFFF;
320+ code1|=0x10400000; // beq v0,zero,xxxx
321+ g_object[pos-1]=code1;
322+ break;
323+ }
324+ break;
325+ default:
326+ break;
327+ }
328+ break;
329+ case 0x0820: // FOR
330+ case 0x0830: // NEXT
331+ case 0x0821: // WHILE
332+ case 0x0831: // WEND
333+ case 0x0822: // DO
334+ case 0x0832: // WHILE
335+ // These are used for detecing the depth of structures.
336+ // Change them to stack increase/decrease commands.
337+ g_object[pos]=0x27BD0000|(code1&0x0000FFFF); //// addiu sp,sp,xx
338+ break;
339+ case 0x2407: // addiu a3,zero,xxxx
340+ if (g_object[pos-1]!=0x02E0F809) break; // jalr ra,s7
341+ // call_lib_code(x)
342+ switch(code1&0x0000FFFF){
343+ case LIB_RESTORE:
344+ // Convert label data to pointer if not dynamic
345+ code1=g_object[pos-3];
346+ code2=g_object[pos-2];
347+ if ((code1>>16)!=0x3C02) break; // lui v0,xxxx
348+ if ((code2>>16)!=0x3442) break; // ori v0,v0,xxxx
349+ label=(code1<<16)|(code2&0x0000FFFF);
350+ code1=(int)search_label(label);
351+ g_label=label;
352+ if (!code1) return ERR_LABEL_NF;
353+ code2=code1&0x0000FFFF;
354+ code1=code1>>16;
355+ g_object[pos-3]=0x3C020000|code1; // lui v0,xxxx
356+ g_object[pos-2]=0x34420000|code2; // ori v0,v0,xxxx
357+ g_object[pos]=0x24070000|LIB_RESTORE2; // addiu a3,zero,xxxx
358+ break;
359+ default:
360+ break;
361+ }
362+ break;
183363 default:
184364 break;
185365 }
--- mips/trunk/help.txt (revision 148)
+++ mips/trunk/help.txt (revision 149)
@@ -17,8 +17,9 @@
1717 「CHR$($22)」のように記述することが出来ます。
1818
1919 <命令>
20-以下、x, y, z等は整数値を、x$, y$, z$は文字列を指します。xxx, yyy, zzz,
21-www等は任意のステートメントを指します。[ ]は省略可能である事を示します。
20+以下、x, y, z等は整数値を、x$, y$, z$は文字列を、x#, y#, z#は浮動
21+小数点型実数値を指します。xxx, yyy, zzz, www等は任意のステートメントを
22+指します。[ ]は省略可能である事を示します。
2223
2324 命令同士を「:」で区切ることにより、一行で複数のコマンドを処理すること
2425 が出来ます。
@@ -25,6 +26,10 @@
2526
2627 BGCOLOR r,g,b
2728 背景色指定。
29+BREAK
30+ FOR-NEXT, DO-LOOP, WHILE-WENDループから抜け出す。
31+CDATA x[,y[,z[...]]]
32+ データー列を8ビット整数値で指定する。
2833 CLEAR
2934 すべての文字列型変数と整数型配列を破棄し、整数値を0とする。また、
3035 PCGの使用をやめ、表示キャラクターをリセットする。
@@ -34,12 +39,27 @@
3439 テキスト色指定。
3540 CURSOR x,y
3641 カーソル位置指定。
37-DATA x[,y[,z[...]]]
38- データー列を整数値で指定する。
42+CDATA xxx[,yyy[,zzz[...]]]
43+ データー列を8ビット整数値で指定する。
44+DATA xxx[,yyy[,zzz[...]]]
45+ データー列を整数値もしくは文字列で指定する。
3946 DIM xxx [, yyy [, zzz [, ... ]]]
40- 整数型の一次元配列を割り当てる。
47+ 整数型もしくは浮動小数点型の配列を割り当てる。
4148 xxx,yyy,zzzは、例えば「A(10)」のように記述する。この場合、A(0)から
42- A(10)までの11個の整数型変数が確保される。
49+ A(10)までの11個の整数型変数が確保される。浮動小数点型配列の場合は、
50+ 「A#(10)」の様に記述する。多次元配列も、宣言することが出来る。
51+DO WHILE x
52+LOOP
53+ x が0以外の場合、DO文からLOOP文までのステートメントを繰り返し実行する。
54+DO UNTIL x
55+LOOP
56+ x が0の場合、DO文からLOOP文までのステートメントを繰り返し実行する。
57+DO
58+LOOP WHILE x
59+ DO文からLOOP文までのステートメントを実行し、x が0以外の場合、繰り返す。
60+DO
61+LOOP UNTIL x
62+ DO文からLOOP文までのステートメントを実行し、x が0の場合、繰り返す。
4363 DRAWCOUNT
4464 DRAWCOUNT値を指定する。DRAWCOUNT値に付いては、DRAWCOUNT()関数を
4565 参照。
@@ -53,21 +73,41 @@
5373 までのステートメントを、繰り返し実行する。繰り返しのたび、xの値は
5474 wwwずつ増加する(省略された場合は1ずつ)。「NEXT」の次に何も記述
5575 しないことに注意。
56-GOSUB xxx
57- 現在の実行位置を記憶し、xxx行目(もしくはラベル)に移動する。
76+GOSUB xxx [, yyy [, zzz [, ... ]]]
77+ 現在の実行位置を記憶し、xxx行目(もしくはラベル)に移動する。yyy, zzz
78+ 等は、サブルーチンに引き継がれる引数(ARGS()関数を参照)。
5879 GOTO xxx
5980 xxx行目(もしくはラベル)に移動する。
60-IF x THEN yyy [ ELSE zzz ]
61- xが0以外のとき、yyyを、0のときzzzを実行
81+IF xまたはx# THEN yyy [ ELSE zzz ]
82+ xが0以外のとき、yyyを、0のときzzzを実行。yyyおよびzzzは、複数のステート
83+ メントを「:」で挟んで記述可能。
84+IF xまたはx# THEN
85+xxx
86+[ELSEIF yまたはy# THEN
87+yyy]
88+[ELSE
89+zzz]
90+ENDIF
91+ xが0以外の時xxxを、それ以外で且つyが0以外の時(記述された場合)yyyを、
92+ それ以外の場合にzzzを実行。ELSEIFステートメントは、複数記述可。各行で、
93+ THENステートメントの次には何も記入しないことに注意。
6294 LABEL xxx
6395 GOTO/GOSUBのジャンプ先を登録する。xxxは、英数字6文字以内の文字列。
6496 [LET] x=yyy
65- yで示された計算結果を、xに代入する。「LET」は省略可。
97+ yで示された計算結果を、x(整数型変数)に代入する。「LET」は省略可。
98+[LET] x#=yyy
99+ yで示された計算結果を、x(不動州数点方型変数)に代入する。「LET」は省略可。
66100 [LET] x$=yyy
67101 yyyで示された文字列(もしくは連結結果;連結演算子は「+」)を、x$に
68102 代入する。「LET」は省略可。
69103 MUSIC x$
70104 BGMを演奏する。詳細は、下記<MUSIC>の項を参照。
105+VAR xxx [, yyy [, zzz [, ... ]]]
106+ サブルーチン内で使う、ローカル変数を指定する。xxx, yyy等は、A-Zの
107+ アルファベットで指定する。
108+WHILE x
109+WEND
110+ x が0以外の場合、WHILE文からWEND文までのステートメントを繰り返し実行する。
71111 PALETTE n,r,g,b
72112 パレット指定。
73113 PCG x,y,z
@@ -75,7 +115,7 @@
75115 ターデーター。詳細は、下記<PCG>の項を参照。
76116 POKE x,y
77117 xで示される物理的アドレスに、yで示される値(1バイト値)を書き込む。
78-PRINT [ xまたはx$ [ ,または; [ yまたはy$ [ ... ]]]]
118+PRINT [ xまたはx$またはx# [ ,または; [ yまたはy$またはy# [ ... ]]]]
79119 ディスプレイに、整数値または文字列を表示する。「;」を使用した場
80120 合、次の表示が続けて行われる。「,」を使用した場合、10文字ずつ
81121 に区切って表示される。どちらも使用しない場合、次の表示は行を変え
@@ -93,6 +133,14 @@
93133 SOUND xxx
94134 効果音を再生する。詳細は、下記<SOUND>の項を参照。xxxは行番号もしく
95135 はラベル。
136+SYSTEM x , y
137+ 様々なシステム値の設定を行なう。<SYSTEM>の項を参照。
138+USEGRAPHIC [x]
139+ グラフィックディスプレイを使用、もしくは使用停止する。x=0で使用停止、
140+ x=1で使用、x=2で画面とパレットをクリアーして使用、x=3でグラフィック領
141+ 域を確保するが表示はキャラクターディスプレイのまま。ただし、グラフィッ
142+ クディスプレイ未使用の状態でx=0の場合は、領域を確保する。xを省略した場
143+ 合は、x=1と同じ。
96144 USEPCG [x]
97145 PCGを使用、もしくは使用停止する。x=0で使用停止、x=1で使用、x=2で
98146 キャラクターをリセットして使用。xを省略した場合は、x=1と同じ。
@@ -101,24 +149,62 @@
101149 xで示された時間、プログラムの実行を停止する。xが60の場合、約1秒間
102150 停止。
103151
104-<関数>
152+<グラフィック関連命令>
153+
154+BOXFILL [x1,y1],x2,y2[,c]
155+ 座標(x1,y1),(x2,y2)を対角線とするカラーcで塗られた長方形を描画。
156+CIRCLE [x,y],r[,c]
157+ 座標(x,y)を中心に、半径r、カラーcの円を描画。
158+CIRCLEFILL [x,y],r[,c]
159+ 座標(x,y)を中心に、半径r、カラーcで塗られた円を描画。
160+GCLS
161+ 画面クリアー。
162+GCOLOR c
163+ それぞれの命令で、cを省略した場合の色を指定。
164+GPALETTE n,r,g,b
165+ パレット指定。
166+GPRINT [x,y],c,bc,s$
167+ 座標(x,y)にカラーcで文字列s$を表示、bc:背景色(負数の場合背景色指定なし)。
168+LINE [x1,y1],x2,y2[,c]
169+ 座標(x1,y1)から(x2,y2)にカラーcで線分を描画。
170+POINT x,y
171+ グラフィック現在位置を、設定する。
172+PSET [x,y][,c]
173+ 座標(x,y)の位置にカラーcで点を描画。
174+PUTBMP [x,y],m,n,bbb
175+ 横m*縦nドットのキャラクター(bbbで指定)を座標(x,y)に表示。
176+ サイズm*nの配列bmpに、単純にカラー番号を並べる。
177+ ただし、カラーが0の部分は透明色として扱う。ただし、bbbはラベル名もし
178+ くは配列へのポインター。
179+
180+<整数型関数>
105181 以下、x, y, zは整数値を、x$, y$, z$は文字列を指します。[ ]は省略可能である事
106182 を示します。
107183
108184 ABS(x)
109185 xの絶対値を返す。
186+ARGS(x)
187+ サブルーチン中で、GOSUBに渡されたx番目の引数を整数値として取り出す。
110188 ASC(x$)
111189 文字列の最初の一文字の、アスキーコードを返す。
190+CREAD()
191+ DATA文の後から、一つずつデーター(8ビット整数値)を読み出す。「READ()」
192+ 関数も参照。
112193 DRAWCOUNT()
113194 DRAWCOUNT値を得る。DRAWCOUNTは16ビット整数値で、1/60秒ごとに1ずつ
114195 増える。
115-GOSUB(xxx)
196+GCOLOR(x,y)
197+ グラフィック座標(x,y)の表示中パレット番号を返す。
198+GOSUB(xxx [, y [, z [, ... ]]])
116199 GOSUB命令と同じだが、戻り値(RETURNを参照)を得ることが出来る。xxxは、
117- ラベルもしくは行番号。
200+ ラベルもしくは行番号。。yyy, zzz 等は、サブルーチンに引き継がれる引数(
201+ ARGS()関数を参照)。
118202 INKEY([x])
119203 xを指定しない場合、現在押されているキーのASCII値を返す。押されていな
120204 い場合は、0。ASCII値でxを指定した場合、そのキーが押されているかどう
121205 かを返す。
206+INT(x#)
207+ 実数値x#を整数値に変換して返す。
122208 KEYS([x])
123209 キー入力を得る。xの値は以下の通り。xを指定しない場合は、x=63と同じ。
124210 KEYUP: 1
@@ -136,7 +222,8 @@
136222 PEEK(x)
137223 xで示される物理アドレスから1バイト読み取り、返す。
138224 READ()
139- DATA文の後から、一つずつデーター(整数値)を読み出す。
225+ DATA文の後から、一つずつデーター(32ビット整数値)を読み出す。「CREAD()」
226+ 関数も参照。
140227 RND()
141228 0から32767までの擬似乱数を返す。
142229 SGN(x)
@@ -143,27 +230,97 @@
143230 xの符号(-1, 0, または1)を返す。
144231 STRNCMP(x$,y$,z)
145232 2つの文字列のうちz文字分を比較し、結果を返す。同じ文字列の場合は0。
233+SYSTEM(x)
234+ 様々なシステム値を、整数値で返す。「<システム変数>」の項を参照。
146235 TVRAM([x])
147236 ビデオRAMのx番目の内容を、バイト値で返す。xを省略した場合、ビデオ
148237 RAMの開始位置の物理アドレスを返す。
149238 VAL(x$)
150239 10進数もしくは16進数文字列としてのx$の値を、整数値で返す。
240+
241+<浮動小数点型関数>
242+ACOS#(x#)
243+ x# の逆余弦を実数値で返す。
244+ARGS#(x)
245+ サブルーチン中で、GOSUBに渡されたx番目の引数を実数値として取り出す。
246+ASIN#(x#)
247+ x# の逆正弦を実数値で返す。
248+ATAN#(x#)
249+ x# の逆正接を実数値で返す。
250+CEIL#(x#)
251+ x# 以上の最小の整数を実数値で返す。
252+COS#(x#)
253+ x# の余弦を実数値で返す。
254+COSH#(x#)
255+ x# の双曲線余弦を実数値で返す。
256+EXP#(x#)
257+ eを底とする x# の指数関数値を実数値で返す。
258+FABS#(x#)
259+ x# の絶対値を実数値で返す。
260+FLOAT#(x)
261+ 整数値 x を浮動小数点型実数値に変換して返す。
262+FLOOR#(x#)
263+ x# 以下の最大の整数を実数値で返す。
264+FMOD#(x#,y#)
265+ x# を y# で割った剰余を実数値で返す。
266+GOSUB#(xxx [, y [, z [, ... ]]])
267+ GOSUB命令と同じだが、戻り値(RETURNを参照)を得ることが出来る。xxxは、
268+ ラベルもしくは行番号。。yyy, zzz 等は、サブルーチンに引き継がれる引数(
269+ ARGS()関数を参照)。
270+LOG#(x#)
271+ x# の自然対数を実数値で返す。
272+LOG10#(x#)
273+ x# の常用対数を実数値で返す。
274+MODF#(x#)
275+ x# の小数部を実数値で返す。
276+PI#
277+ 3.141593を返す。
278+POW#(x#,y#)
279+ x# の y# 乗を実数値で返す。
280+SIN#(x#)
281+ x# の正弦を実数値で返す。
282+SINH#(x#)
283+ x# の双曲線正弦を実数値で返す。
284+SQRT#(x#)
285+ x# の平方根を実数値で返す。
286+TAN#(x#)
287+ x# の正接を実数値で返す。
288+TANH#(x#)
289+ x# の双曲線正接を実数値で返す。
290+VAL#(x$)
291+ 10進数文字列としてのx$の値を、実数値で返す。
292+
293+<文字列型関数>
151294 A$(x [,y])など
152295 xの値が0の場合、文字列全体を返す。
153296 xの値が正の場合、xで示される位置より右側の文字列を返す。
154297 xの値が負のとき、文字列の右側x文字を返す。
155298 yが指定された場合、y文字分の文字列を返す。
299+ARGS$(x)
300+ サブルーチン中で、GOSUBに渡されたx番目の引数を文字列として取り出す。
156301 CHR$(x)
157302 xをアスキーコードとする文字を返す。
158303 DEC$(x)
159304 xの値を、10進数の文字列として返す。
305+FLOAT$(x#)
306+ 実数値x#を、10進数の文字列として返す。
307+GOSUB$(xxx [, y [, z [, ... ]]])
308+ GOSUB命令と同じだが、戻り値(RETURNを参照)を文字列として得ることが出来る。
309+ xxxは、ラベルもしくは行番号。。yyy, zzz 等は、サブルーチンに引き継がれる引数
310+ (ARGS()関数を参照)。
160311 HEX$(x [,y])
161312 xの値を、16進数の文字列として返す。yが指定された場合、yバイト長の
162313 文字列になる。
163314 INPUT$()
164315 文字列入力状態になり、入力が終了すると(Enterが押されると)文字列を返す。
316+SPRINTF$(x$,y#)
317+ x$で示される書式に従って、実数y#の内容を文字列として返す。
318+SYSTEM$(x)
319+ 様々なシステム値を、文字列で返す。「<システム変数>」の項を参照。
320+READ$()
321+ DATA文の後から、一つずつ文字列データーを読み出す。
165322
166-<演算子>
323+<整数演算子>
167324 -x
168325 符号を反転
169326 x + y
@@ -176,6 +333,10 @@
176333 整数除算
177334 x % y
178335 整数剰余
336+x >> y
337+ xの値をyビット右シフト
338+x << y
339+ xの値をyビット左シフト
179340 x = y
180341 2つの整数値が等しい場合に1、そうでないときに0
181342 x != y
@@ -194,8 +355,6 @@
194355 xとyの値のビットごとの OR
195356 x XOR y
196357 xとyの値のビットごとの XOR
197-x$ + y$
198- 文字列の連結
199358
200359 なお、整数演算子の優先順位は、優先度が高いものから以下の順です。
201360
@@ -202,6 +361,7 @@
202361 + - (単項演算子)
203362 * / %
204363 + - (加算・減算)
364+<< >>
205365 < <= > >=
206366 = !=
207367 XOR
@@ -208,6 +368,48 @@
208368 AND
209369 OR
210370
371+<文字列演算子>
372+x$ + y$
373+ 文字列の連結
374+
375+<浮動小数点型演算子>
376+-x#
377+ 符号を反転
378+x# + y#
379+ 実数加算
380+x# - y#
381+ 実数減算
382+x# * y#
383+ 実数乗算
384+x# / y#
385+ 実数除算
386+x# = y#
387+ 2つの実数値が等しい場合に1、そうでないときに0
388+x# != y#
389+ 2つの実数値が等しい場合に0、そうでないときに1
390+x# < y#
391+ xがyより小さい場合に1、そうでないときに0
392+x# <= y#
393+ xがyより小さいか等しい場合に1、そうでないときに0
394+x# > y#
395+ xがyより多きい場合に1、そうでないときに0
396+x# >= y#
397+ xがyより多きいか等しい場合に1、そうでないときに0
398+x# AND y#
399+ xとyの値の論理積(ビットごとの AND でないことに注意)
400+x# OR y#
401+ xとyの値の論理和(ビットごとの OR でないことに注意)
402+
403+なお、実数演算子の優先順位は、優先度が高いものから以下の順です。
404+
405++ - (単項演算子)
406+* /
407++ - (加算・減算)
408+< <= > >=
409+= !=
410+AND
411+OR
412+
211413 <MUSIC>
212414 MUSIC命令では、BGM用のデーターを文字列で指定します。文字列の書式は、ABC
213415 notationに準拠しています。ただし、すべての記法が使えるわけではありません。
@@ -265,12 +467,66 @@
265467
266468 として下さい。
267469
470+<システム変数>
471+SYSTEM関数及びSYSTEMステートメントを用いて、各種システム情報をやりとりするこ
472+とが出来ます。
473+
474+SYSTEM$(0)
475+ MachiKania バージョン文字列、"Zoea"を返す。
476+SYSTEM$(1)
477+ MachiKania バージョン文字列、"1.0"等を返す。
478+SYSTEM$(2)
479+ BASIC バージョン文字列、"KM-1200"等を返す。
480+SYSTEM$(3)
481+ 現在実行中のHEXファイル名、"ZOEA.HEX"等を返す。
482+SYSTEM(20)
483+ キャラクターディスプレイ横幅を返す。
484+SYSTEM(21)
485+ キャラクターディスプレイ縦幅を返す。
486+SYSTEM(22)
487+ グラフィックディスプレイ横幅を返す。
488+SYSTEM(23)
489+ グラフィックディスプレイ横幅を返す。
490+SYSTEM(24)
491+ キャラクターディスプレイ用の指定色を返す。
492+SYSTEM(25)
493+ グラフィックディスプレイ用の指定色を返す。
494+SYSTEM(26)
495+ キャラクターディスプレイの、現在のX位置を返す。
496+SYSTEM(27)
497+ キャラクターディスプレイの、現在のY位置を返す。
498+SYSTEM(28)
499+ グラフィックディスプレイの、現在のX位置を返す。
500+SYSTEM(29)
501+ グラフィックディスプレイの、現在のY位置を返す。
502+SYSTEM(40)
503+ PS/2キーボードを使用中かどうかを返す。
504+SYSTEM(41)
505+ PS/2キーボード情報、vkeyを返す。
506+SYSTEM(42)
507+ PS/2キーボード情報、lockkeyを返す。
508+SYSTEM(43)
509+ PS/2キーボード情報、keytypeを返す。
510+SYSTEM(100)
511+ 変数格納領域(g_var_mem)へのポインターを返す。
512+SYSTEM(101)
513+ 乱数シードへのポインターを返す。
514+SYSTEM(102)
515+ キャラクターディスプレイ領域(TVRAM)へのポインターを返す。
516+SYSTEM(103)
517+ フォント領域へのポインターを返す。
518+SYSTEM(104)
519+ PCGフォント領域へのポインターを返す。
520+SYSTEM(105)
521+ グラフィックディスプレイ領域へのポインターを返す。
522+SYSTEM 200,x
523+ ディスプレイの表示を停止(xが0のとき)、もしくは開始(xが0以外の時)する。
524+
268525 <ヒント>
269-FOR文では、TOステートメントの次に書かれた値に合致する場合(超えた時ではなく)
270-に、ループから抜ける仕様です。また、FOR-NEXTループの途中で、GOTO文でループの
526+FOR-NEXTループ、WHILE-WENDループ、DO-LOOPループの途中で、GOTO文でループの
271527 外に飛んだり、RETURN文を実行したりすると、予期せぬ結果(機器のリセット等)を
272-引き起こします。ただし、GOSUB文でサブルーチンを呼んだり、別のFOR-NEXTをネス
273-トして使う事は可能です。
528+引き起こします。ただし、GOSUB文でサブルーチンを呼んだり、別のループをネスト
529+して使う事は可能です。
274530
275531 ON GOTO分やON GOSUB文はサポートしていません。ただし、例えば次のように記述す
276532 ることで、同様の動作をさせることは可能です。
@@ -286,6 +542,24 @@
286542 てみて下さい。
287543
288544 <バージョン履歴>
545+・KM-1200 2016年8月公開。
546+ 1.グラフィックディスプレイ機能および、関連のステートメント群を追加。
547+ 2.浮動小数点演算機能、及び、算術演算関数群を追加。
548+ 3.VAR, BREAK, SYSTEMステートメントを追加。
549+ 4.DO-LOOP, WHILE-WENDループ構造文を追加。
550+ 5.IF THEN - ELSEIF - ELSE - ENDIFによる、複数行での条件分岐表現を追加。
551+ 6.GOSUBステートメント及びGOSUB()関数に第二以降の引数を指定出来る様にし、
552+   サブルーチン中でARGS()関数により取り出せるようにした。
553+ 7.8ビット整数型を扱うCDATAステートメントとCREAD()関数を追加。
554+ 8.DATAステートメントで文字列を扱える様にし、READ$()で読めるようにした。
555+ 9.多次元配列をサポート。
556+ 10.例外発生時に、情報を表示するようにした。
557+ 11.FOR-NEXTループに於いて、TO値に一致する時だけではなく、値を超えた場合
558+   でもループを抜けるようにした。
559+ 12.MUSICステートメント用のスクリプトにエラーがある際、エラー発生行が正し
560+   く表示されない不具合を修正。
561+ 13.ビットシフト演算子を、追加。
562+
289563 ・KM-1120 2016年2月公開。
290564  1.PCG機能を追加。
291565  2.SCROLL命令を追加。
--- mips/trunk/debug.c (nonexistent)
+++ mips/trunk/debug.c (revision 149)
@@ -0,0 +1,160 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by K.Tanaka & Katsumi
4+ http://www.ze.em-net.ne.jp/~kenken/index.html
5+ http://hp.vector.co.jp/authors/VA016157/
6+*/
7+
8+#ifdef __DEBUG
9+
10+#include <xc.h>
11+#include "api.h"
12+#include "main.h"
13+
14+
15+// Pseudo reading config setting for debug mode
16+unsigned int g_DEVCFG1=0xFF7F4DDB;
17+
18+// Construct jump assembly in boot area.
19+const unsigned int _debug_boot[] __attribute__((address(0xBFC00000))) ={
20+ 0x0B401C00,// j 0x9d007000
21+ 0x00000000,// nop
22+};
23+
24+// Use DEBUG.HEX as file name of this program.
25+const unsigned char _debug_filename[] __attribute__((address(FILENAME_FLASH_ADDRESS))) ="DEBUG.HEX";
26+
27+static const char initext[];
28+static const char bastext[];
29+
30+static char* readtext;
31+static int filepos;
32+
33+/*
34+ Override libsdfsio functions.
35+ Here, don't use SD card, but the vertual files
36+ (initext[] and bastext[]) are used.
37+*/
38+
39+FSFILE fsfile;
40+
41+size_t FSfread(void *ptr, size_t size, size_t n, FSFILE *stream){
42+ char b;
43+ size_t ret=0;
44+ if (!readtext) return 0;
45+ while(b=readtext[filepos]){
46+ filepos++;
47+ ((char*)ptr)[ret]=b;
48+ ret++;
49+ if (n<=ret) break;
50+ }
51+ return ret;
52+}
53+FSFILE* FSfopen(const char * fileName, const char *mode){
54+ int i;
55+ for(i=0;i<13;i++){
56+ if (fileName[i]=='.') break;
57+ }
58+ if (i==13) {
59+ // Unknown file name
60+ // Force BAS file
61+ readtext=(char*)&bastext[0];
62+ } else if (fileName[i+1]=='I' && fileName[i+2]=='N' && fileName[i+3]=='I') {
63+ // INI file
64+ readtext=(char*)&initext[0];
65+ } else if (fileName[i+1]=='B' && fileName[i+2]=='A' && fileName[i+3]=='S') {
66+ // BAS file
67+ readtext=(char*)&bastext[0];
68+ } else {
69+ readtext=0;
70+ return 0;
71+ }
72+ filepos=0;
73+ return &fsfile;
74+}
75+int FSfeof( FSFILE * stream ){
76+ return readtext[filepos]?1:0;
77+}
78+int FSfclose(FSFILE *fo){
79+ return 0;
80+}
81+int FSInit(void){
82+ return 1;
83+}
84+int FSremove (const char * fileName){
85+ return 0;
86+}
87+size_t FSfwrite(const void *ptr, size_t size, size_t n, FSFILE *stream){
88+ return 0;
89+}
90+
91+int FindFirst (const char * fileName, unsigned int attr, SearchRec * rec){
92+ return 0;
93+}
94+int FindNext (SearchRec * rec){
95+ return 0;
96+}
97+
98+/*
99+ ps2init() is not called.
100+ Instead, not_ps2init_but_init_Timer1() is called.
101+ Timer1 is used to update drawcount and drawing gloval variables.
102+*/
103+
104+int not_ps2init_but_init_Timer1(){
105+ PR1=0x0FFF;
106+ TMR1=0;
107+ IFS0bits.T1IF=0;
108+ T1CON=0x8000;
109+ // Timer1 interrupt: priority 4
110+ IPC1bits.T1IP=4;
111+ IPC1bits.T1IS=0;
112+ IEC0bits.T1IE=1;
113+
114+ return 0;
115+}
116+
117+#pragma interrupt timer1Int IPL4SOFT vector 4
118+
119+void timer1Int(){
120+ IFS0bits.T1IF=0;
121+ if (drawing) {
122+ drawing=0;
123+ drawcount++;
124+ } else {
125+ drawing=1;
126+ }
127+}
128+
129+/*
130+ initext[] and bastext[] are vertual files
131+ as "MACHIKAN.INI" and "DEBUG.BAS".
132+*/
133+
134+
135+static const char initext[]=
136+"#PRINT\n"
137+"#PRINT\n";
138+
139+
140+static const char bastext[]=
141+"CLS\n"
142+"\n";
143+
144+/*
145+ Test function for constructing assemblies from C codes.
146+*/
147+
148+int _debug_test(int a0, int a1){
149+// if (a0<0xa0008192) return 0xa0000000;
150+ asm volatile("lw $v1,0($v1)");
151+}
152+
153+/*
154+ Break point used for debugging object code.
155+
156+g_object[g_objpos++]=0x0000000d;// break 0x0
157+
158+*/
159+
160+#endif // __DEBUG
--- mips/trunk/editor.c (revision 148)
+++ mips/trunk/editor.c (revision 149)
@@ -9,6 +9,7 @@
99 #include "editor.h"
1010 #include "keyinput.h"
1111 #include "compiler.h"
12+#include "main.h"
1213
1314 struct _TBUF{
1415 //リンク付きのテキストバッファ
@@ -61,7 +62,7 @@
6162 void wait60thsec(unsigned short n){
6263 // 60分のn秒ウェイト(ビデオ画面の最下行信号出力終了まで待つ)
6364 n+=drawcount;
64- while(drawcount!=n) asm("wait");
65+ while(drawcount!=n) asm(WAIT);
6566 }
6667
6768 unsigned int bpixtopos(_tbuf *bp,unsigned int ix){
@@ -102,23 +103,30 @@
102103 // テキスト全体の先頭からline行目のテキストバッファ上の位置を返す
103104 // 戻り値 テキストバッファポインタ
104105 // *pix(戻り値):戻り値テキストバッファの先頭からの位置(ポインタ渡し)
105- _tbuf *bp;
106- int ix;
106+ _tbuf *bp,*bp2;
107+ int ix,ix2;
107108 bp=TBufstart;
109+ bp2=TBufstart;
108110 ix=0;
111+ ix2=0;
109112 while(line>1){
110113 while(1){
111114 if(ix>=bp->n){
115+ if(bp->next==NULL) break;
112116 bp=bp->next;
113117 ix=0;
114118 continue;
115119 }
116- if(bp->Buf[ix++] == '\n') break;
120+ if(bp->Buf[ix++] == '\n'){
121+ bp2=bp;
122+ ix2=ix;
123+ break;
124+ }
117125 }
118126 line--;
119127 }
120- *pix=ix;
121- return bp;
128+ *pix=ix2;
129+ return bp2;
122130 }
123131
124132 _tbuf * newTBuf(_tbuf *prev){
@@ -1015,7 +1023,7 @@
10151023 if(vk==VK_ESCAPE) return -1;
10161024 }
10171025 //ファイルシステム初期化
1018- if(FSInit()!=NULL) return 0; //成功
1026+ if(FSInit()!=FALSE) return 0; //成功
10191027 //エラーの場合
10201028 setcursorcolor(COLOR_ERRORTEXT);
10211029 printstr((unsigned char *)Message2);//File System Error
--- mips/trunk/error.c (revision 148)
+++ mips/trunk/error.c (revision 149)
@@ -14,14 +14,18 @@
1414 "Divided by zero",
1515 "Not yet implemented",
1616 "Label or line number not found: ",
17- "Label too long",
17+ "Label too long or too short",
1818 "String too complexed",
1919 "Data not found",
2020 "Unknown error",
21- "Music syntax error\n",
21+ "Music syntax error:'",
2222 " found more than twice",
2323 "Break",
2424 "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 ",
2529 };
2630
2731 char* resolve_label(int s6){
@@ -61,7 +65,7 @@
6165 void pre_end_addr(int s6){
6266 int i,j;
6367 char str[7];
64- if (s6<0) s6=0-s6;
68+ if (s6<0) s6=s6&0x7fffffff;
6569 g_label=s6;
6670 if (s6<65536) {
6771 // Line number
@@ -121,6 +125,10 @@
121125 void err_music(char* str){
122126 printstr(ERR_MUSIC);
123127 printstr(str);
128+ printstr("'\n");
129+ // Restore s6 from g_s6
130+ asm volatile("la $s6,%0"::"i"(&g_s6));
131+ asm volatile("lw $s6,0($s6)");
124132 end_exec();
125133 }
126134
@@ -128,3 +136,8 @@
128136 printstr(ERR_UNEXP_NEXT);
129137 end_exec();
130138 }
139+
140+void err_no_block(void){
141+ printstr(ERR_NO_BLOCK);
142+ end_exec();
143+}
--- mips/trunk/main.h (nonexistent)
+++ mips/trunk/main.h (revision 149)
@@ -0,0 +1,21 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by K.Tanaka & Katsumi
4+ http://www.ze.em-net.ne.jp/~kenken/index.html
5+ http://hp.vector.co.jp/authors/VA016157/
6+*/
7+
8+#define SYSVER1 "Zoea"
9+#define SYSVER2 "1.0"
10+#define BASVER "KM-1200"
11+
12+#define INIFILE "MACHIKAZ.INI" // 初期設定ファイル
13+#define HEXFILE "MACHIKAZ.HEX" // 実行中HEXファイル名がこれと一致した場合はエディタ起動
14+
15+#define FILENAME_FLASH_ADDRESS 0x9D005800
16+#define PIC32MX_RAMSIZE 0x10000
17+#define PIC32MX_FLASHSIZE 0x40000
18+
19+void printhex8(unsigned char d);
20+void printhex16(unsigned short d);
21+void printhex32(unsigned int d);
--- mips/trunk/debug.h (nonexistent)
+++ mips/trunk/debug.h (revision 149)
@@ -0,0 +1,25 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by K.Tanaka & Katsumi
4+ http://www.ze.em-net.ne.jp/~kenken/index.html
5+ http://hp.vector.co.jp/authors/VA016157/
6+*/
7+
8+#ifdef __DEBUG
9+
10+// Pseudo reading config setting for debug mode
11+extern unsigned int g_DEVCFG1;
12+#define DEVCFG1 g_DEVCFG1
13+
14+// Do not use PS/2 keyboard
15+#define ps2init() not_ps2init_but_init_Timer1()
16+int not_ps2init_but_init_Timer1();
17+
18+// Do not use set_graphmode()
19+#define set_graphmode(m) (0)
20+
21+// Do not use asm("wait") but use asm("nop")
22+#undef WAIT
23+#define WAIT "nop"
24+
25+#endif // __DEBUG
--- mips/trunk/operator.c (revision 148)
+++ mips/trunk/operator.c (revision 149)
@@ -12,6 +12,7 @@
1212 ()
1313 * / %
1414 + -
15+<< >>
1516 < <= > >=
1617 = !=
1718 XOR
@@ -27,8 +28,9 @@
2728 3, // OP_XOR
2829 4,4, // OP_EQ, OP_NEQ
2930 5,5,5,5, // OP_LT, OP_LTE, OP_MT, OP_MTE
30- 6,6, // OP_ADD, OP_SUB
31- 7,7,7 // OP_MUL, OP_DIV, OP_REM
31+ 6,6, // OP_SHL, OP_SHR
32+ 7,7, // OP_ADD, OP_SUB
33+ 8,8,8 // OP_MUL, OP_DIV, OP_REM
3234 };
3335
3436 enum operator g_last_op;
@@ -46,8 +48,11 @@
4648 case '-': g_last_op=OP_SUB; break;
4749 case '+': g_last_op=OP_ADD; break;
4850 case '>':
49- if (b2=='=') {
51+ if (b2=='>') {
5052 g_srcpos++;
53+ g_last_op=OP_SHR;
54+ } else if (b2=='=') {
55+ g_srcpos++;
5156 g_last_op=OP_MTE;
5257 } else {
5358 g_last_op=OP_MT;
@@ -54,8 +59,11 @@
5459 }
5560 break;
5661 case '<':
57- if (b2=='=') {
62+ if (b2=='<') {
5863 g_srcpos++;
64+ g_last_op=OP_SHL;
65+ } else if (b2=='=') {
66+ g_srcpos++;
5967 g_last_op=OP_LTE;
6068 } else {
6169 g_last_op=OP_LT;
@@ -96,8 +104,28 @@
96104 return 0;
97105 }
98106
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+
99127 char* calculation(enum operator op){
100- // $v0 = $v0 <op> $v1;
128+ // $v0 = $v1 <op> $v0;
101129 switch(op){
102130 case OP_OR:
103131 check_obj_space(1);
@@ -139,6 +167,14 @@
139167 g_object[g_objpos++]=0x0062102A; // slt v0,v1,v0
140168 g_object[g_objpos++]=0x38420001; // xori v0,v0,0x1
141169 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;
142178 case OP_ADD:
143179 check_obj_space(1);
144180 g_object[g_objpos++]=0x00621021; // addu v0,v1,v0
@@ -173,4 +209,67 @@
173209 return ERR_SYNTAX;
174210 }
175211 return 0;
176-}
\ No newline at end of file
212+}
213+
214+char* calculation_float(enum operator op){
215+ // $v0 = $a0 <op> $v0;
216+ check_obj_space(1);
217+ g_object[g_objpos++]=0x34050000|(op&0x0000FFFF); // ori a1,zero,xxxx
218+ // All the calculations will be done in library code, lib_float function (see below).
219+ call_lib_code(LIB_FLOAT);
220+ return 0;
221+}
222+
223+int lib_float(int ia0,int iv0, enum operator a1){
224+ // This function was called from _call_library().
225+ // Variable types must be all int.
226+ // Casting cannot be used.
227+ // Instead, by using pointer, put as int value, get as float value,
228+ // calculate, put as float value, then get as int value for returning.
229+ volatile float a0,v0;
230+ ((int*)(&a0))[0]=ia0;
231+ ((int*)(&v0))[0]=iv0;
232+ switch(a1){
233+ case OP_EQ:
234+ v0= a0==v0?1:0;
235+ break;
236+ case OP_NEQ:
237+ v0= a0!=v0?1:0;
238+ break;
239+ case OP_LT:
240+ v0= a0<v0?1:0;
241+ break;
242+ case OP_LTE:
243+ v0= a0<=v0?1:0;
244+ break;
245+ case OP_MT:
246+ v0= a0>v0?1:0;
247+ break;
248+ case OP_MTE:
249+ v0= a0>=v0?1:0;
250+ break;
251+ case OP_ADD:
252+ v0= a0+v0;
253+ break;
254+ case OP_SUB:
255+ v0= a0-v0;
256+ break;
257+ case OP_MUL:
258+ v0= a0*v0;
259+ break;
260+ case OP_DIV:
261+ if (v0==0) err_div_zero();
262+ v0= a0/v0;
263+ break;
264+ case OP_OR:
265+ v0= a0||v0?1:0;
266+ break;
267+ case OP_AND:
268+ v0= a0&&v0?1:0;
269+ break;
270+ default:
271+ err_unknown();
272+ return 0;
273+ }
274+ return ((int*)(&v0))[0];
275+};
\ No newline at end of file
--- mips/trunk/editor.h (revision 148)
+++ mips/trunk/editor.h (revision 149)
@@ -4,7 +4,8 @@
44 http://www.ze.em-net.ne.jp/~kenken/index.html
55 */
66
7-#define TBUFMAXLINE 101 //テキストバッファ数
7+#define TBUFMAXLINE 201 //テキストバッファ数
8+
89 #define TBUFSIZE 200 //テキストバッファ1つのサイズ
910 #define TBUFMAXSIZE (TBUFSIZE*(TBUFMAXLINE-1)) //最大バッファ容量(バッファ1行分空ける)
1011 #define EDITWIDTHX 30 //エディタ画面横幅
@@ -21,9 +22,8 @@
2122 #define ERR_CANTWRITEFILE -3
2223
2324 #define TEMPFILENAME "~TEMP.BAS"
24-#define INIFILE "MACHIKAN.INI" // 初期設定ファイル
25-#define HEXFILE "MACHIKAN.HEX" // 実行中HEXファイル名がこれと一致した場合はエディタ起動
2625
2726 void texteditor(void); //テキストエディタ本体
2827 int runbasic(char *s,int test); //コンパイルして実行
2928 extern unsigned char tempfile[13];
29+void wait60thsec(unsigned short n);
--- mips/trunk/exception.c (nonexistent)
+++ mips/trunk/exception.c (revision 149)
@@ -0,0 +1,126 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by K.Tanaka & Katsumi
4+ http://www.ze.em-net.ne.jp/~kenken/index.html
5+ http://hp.vector.co.jp/authors/VA016157/
6+*/
7+
8+#include <xc.h>
9+#include "api.h"
10+#include "main.h"
11+#include "compiler.h"
12+
13+void _general_exception_handler (void){
14+ int i;
15+ // $v1 is g_ex_data
16+ asm volatile("la $v1,%0"::"i"(&g_ex_data[0]));
17+ // Prepare proper stack area before SoftReset
18+ asm volatile("addiu $sp,$v1,0xfff0");
19+ // g_ex_data[2]=$s6
20+ asm volatile("sw $s6,8($v1)");
21+ // g_ex_data[3]=Cause
22+ asm volatile("mfc0 $v0,$13");
23+ asm volatile("sw $v0,12($v1)");
24+ // g_ex_data[4]=EPC
25+ asm volatile("mfc0 $v0,$14");
26+ asm volatile("sw $v0,16($v1)");
27+ // Exception occured
28+ g_ex_data[0]=1;
29+ // g_s6
30+ g_ex_data[1]=g_s6;
31+ // Clear 2 MLB bits of EPC
32+ g_ex_data[4]&=0xfffffffc;
33+ // If EPC is within RAM, store data in exception area.
34+ if ((int)(&RAM[0])<=g_ex_data[4] && g_ex_data[4] <(int)(&RAM[RAMSIZE])) {
35+ // g_ex_data[5] - g_ex_data[12]: assembly
36+ for(i=-3;i<=3;i++){
37+ g_ex_data[i+8]=((int*)g_ex_data[4])[i];
38+ }
39+ }
40+ // Wait until all buttons are released and reset MachiKania.
41+ #ifdef __DEBUG
42+ asm volatile("j 0xBFC00000");
43+ #else
44+ buttonmode();
45+ for(i=0;i<100000;i++){
46+ if((KEYPORT&(KEYUP|KEYDOWN|KEYLEFT|KEYRIGHT|KEYSTART|KEYFIRE))
47+ !=(KEYUP|KEYDOWN|KEYLEFT|KEYRIGHT|KEYSTART|KEYFIRE)) i=0;
48+ }
49+ asm volatile("j SoftReset");
50+ #endif
51+}
52+
53+void blue_screen(void){
54+ int i,j,s6,s6g;
55+ unsigned int* opos;
56+ if (RCONbits.POR || RCONbits.EXTR) {
57+ // After power on or reset. Reset flags and return.
58+ RCONbits.POR=0;
59+ RCONbits.EXTR=0;
60+ for(i=0;i<RAMSIZE;i++){
61+ // Reset all RAM area including g_ex_data[]
62+ RAM[i]=0;
63+ }
64+ return;
65+ } else if (g_ex_data[0]==0) {
66+ // No exception found.
67+ return;
68+ }
69+ // Exception occured before SoftReset().
70+ // Prepare data
71+ s6=g_ex_data[2];
72+ s6g=g_ex_data[1];
73+ s6=s6&0x7fffffff;
74+ s6g=s6g&0x7fffffff;
75+ opos=(int*)g_ex_data[4];
76+ //set_bgcolor(255,0,0);
77+ printstr("STOP");
78+ printstr("\nException at ");
79+ printhex32(g_ex_data[4]);
80+ printstr("\n Cause: ");
81+ printhex32(g_ex_data[3]);
82+ printstr("\n ");
83+ switch((g_ex_data[3]>>2)&0x1f){
84+ case 0: printstr("(Interrupt)"); break;
85+ case 1: printstr("(TLB modification)"); break;
86+ case 2: printstr("(TLB load/fetch)"); break;
87+ case 3: printstr("(TLB store)"); break;
88+ case 4: printstr("(Address load/fetch error )"); break;
89+ case 5: printstr("(Address store error)"); break;
90+ case 6: printstr("(Bus fetch error)"); break;
91+ case 7: printstr("(Bus load/store error)"); break;
92+ case 8: printstr("(Syscall)"); break;
93+ case 9: printstr("(Breakpoint)"); break;
94+ case 10: printstr("(Reserved instruction)"); break;
95+ case 11: printstr("(Coprocessor Unusable)"); break;
96+ case 12: printstr("(Integer Overflow)"); break;
97+ case 13: printstr("(Trap)"); break;
98+ case 23: printstr("(Reference to Watch address)"); break;
99+ case 24: printstr("(Machine check)"); break;
100+ default: printstr("(Unknown)"); break;
101+ }
102+ printstr("\n s6: ");
103+ printstr(resolve_label(s6));
104+ printstr("\n g_s6: ");
105+ printstr(resolve_label(s6g));
106+ printstr("\n");
107+ printstr("Reset MachiKania to contine.\n\n");
108+ // Show code where the exception happened.
109+ for(i=-3;i<=3;i++){
110+ printstr("\n ");
111+ printhex32((unsigned int)&opos[i]);
112+ printstr(" ");
113+ if ((unsigned int)&RAM[0]<=(unsigned int)&opos[i] && (unsigned int)&opos[i]<(unsigned int)&RAM[RAMSIZE]) {
114+ // Exception in RAM[RAMSIZE] area
115+ printhex32(g_ex_data[i+8]);
116+ } else if ( 0xA0000000<=(unsigned int)&opos[i] && (unsigned int)&opos[i]<0xA0000000+PIC32MX_RAMSIZE
117+ || 0x9D000000<=(unsigned int)&opos[i] && (unsigned int)&opos[i]<=0x9D000000+PIC32MX_FLASHSIZE) {
118+ // Exception in outside RAM[RAMSIZE] or flash area
119+ printhex32(opos[i]);
120+ } else {
121+ printstr("********");
122+ }
123+ }
124+ printstr("\n");
125+ while(1) asm("wait");
126+}
--- mips/trunk/videoout.h (nonexistent)
+++ mips/trunk/videoout.h (revision 149)
@@ -0,0 +1,108 @@
1+#define WIDTH_X 30 // 横方向文字数
2+#define WIDTH_Y 27 // 縦方向文字数
3+#define ATTROFFSET (WIDTH_X*WIDTH_Y) // VRAM上のカラーパレット格納位置
4+
5+#define G_X_RES 256 // 横方向解像度
6+#define G_Y_RES 224 // 縦方向解像度
7+#define G_H_WORD (G_X_RES/4) // 1行当りのワード数(16bit単位)
8+
9+
10+// 入力ボタンのポート、ビット定義
11+#define KEYPORT PORTB
12+#define KEYUP 0x0400
13+#define KEYDOWN 0x0080
14+#define KEYLEFT 0x0100
15+#define KEYRIGHT 0x0200
16+#define KEYSTART 0x0800
17+#define KEYFIRE 0x4000
18+
19+extern volatile char drawing; // 表示期間中は-1
20+extern volatile unsigned short drawcount; // 1画面表示終了ごとに1足す。アプリ側で0にする。
21+ // 最低1回は画面表示したことのチェックと、アプリの処理が何画面期間必要かの確認に利用。
22+extern unsigned char TVRAM[]; //テキストビデオメモリ
23+extern unsigned short *gVRAM; //グラフィックVRAM開始位置のポインタ
24+
25+extern const unsigned char FontData[]; //フォントパターン定義
26+extern unsigned char *cursor;
27+extern unsigned char cursorcolor;
28+extern unsigned char *fontp;
29+
30+void start_composite(void); //カラーコンポジット出力開始
31+void stop_composite(void); //カラーコンポジット出力停止
32+void init_composite(void); //カラーコンポジット出力初期化
33+void clearscreen(void); //テキスト画面クリア
34+void set_palette(unsigned char n,unsigned char b,unsigned char r,unsigned char g); //テキストパレット設定
35+void set_bgcolor(unsigned char b,unsigned char r,unsigned char g); //バックグランドカラー設定
36+void set_graphmode(unsigned char m); //グラフィックモード変更
37+void init_graphic(unsigned short *gvram); //グラフィック機能利用準備
38+
39+void vramscroll(void);
40+ //1行スクロール
41+void setcursor(unsigned char x,unsigned char y,unsigned char c);
42+ //カーソル位置とカラーを設定
43+void setcursorcolor(unsigned char c);
44+ //カーソル位置そのままでカラー番号をcに設定
45+void printchar(unsigned char n);
46+ //カーソル位置にテキストコードnを1文字表示し、カーソルを1文字進める
47+void printstr(unsigned char *s);
48+ //カーソル位置に文字列sを表示
49+void printnum(unsigned int n);
50+ //カーソル位置に符号なし整数nを10進数表示
51+void printnum2(unsigned int n,unsigned char e);
52+ //カーソル位置に符号なし整数nをe桁の10進数表示(前の空き桁部分はスペースで埋める)
53+void cls(void);
54+ //テキスト画面消去し、カーソルを先頭に移動
55+void startPCG(unsigned char *p,int a);
56+ // RAMフォント(PCG)の利用開始、pがフォント格納場所、aが0以外でシステムフォントをコピー
57+void stopPCG(void);
58+ // RAMフォント(PCG)の利用停止
59+
60+void g_clearscreen(void);
61+//グラフィック画面クリア
62+void g_set_palette(unsigned char n,unsigned char b,unsigned char r,unsigned char g);
63+//グラフィック用カラーパレット設定
64+
65+void g_pset(int x,int y,unsigned int c);
66+// (x,y)の位置にカラーcで点を描画
67+
68+void g_putbmpmn(int x,int y,char m,char n,const unsigned char bmp[]);
69+// 横m*縦nドットのキャラクターを座標x,yに表示
70+// unsigned char bmp[m*n]配列に、単純にカラー番号を並べる
71+// カラー番号が0の部分は透明色として扱う
72+
73+void g_clrbmpmn(int x,int y,char m,char n);
74+// 縦m*横nドットのキャラクター消去
75+// カラー0で塗りつぶし
76+
77+void g_gline(int x1,int y1,int x2,int y2,unsigned int c);
78+// (x1,y1)-(x2,y2)にカラーcで線分を描画
79+
80+void g_hline(int x1,int x2,int y,unsigned int c);
81+// (x1,y)-(x2,y)への水平ラインを高速描画
82+
83+void g_circle(int x0,int y0,unsigned int r,unsigned int c);
84+// (x0,y0)を中心に、半径r、カラーcの円を描画
85+
86+void g_boxfill(int x1,int y1,int x2,int y2,unsigned int c);
87+// (x1,y1),(x2,y2)を対角線とするカラーcで塗られた長方形を描画
88+
89+void g_circlefill(int x0,int y0,unsigned int r,unsigned int c);
90+// (x0,y0)を中心に、半径r、カラーcで塗られた円を描画
91+
92+void g_putfont(int x,int y,unsigned int c,int bc,unsigned char n);
93+//8*8ドットのアルファベットフォント表示
94+//座標(x,y)、カラー番号c
95+//bc:バックグランドカラー、負数の場合無視
96+//n:文字番号
97+
98+void g_printstr(int x,int y,unsigned int c,int bc,unsigned char *s);
99+//座標(x,y)からカラー番号cで文字列sを表示、bc:バックグランドカラー
100+
101+void g_printnum(int x,int y,unsigned char c,int bc,unsigned int n);
102+//座標(x,y)にカラー番号cで数値nを表示、bc:バックグランドカラー
103+
104+void g_printnum2(int x,int y,unsigned char c,int bc,unsigned int n,unsigned char e);
105+//座標(x,y)にカラー番号cで数値nを表示、bc:バックグランドカラー、e桁で表示
106+
107+unsigned int g_color(int x,int y);
108+//座標(x,y)のVRAM上の現在のパレット番号を返す、画面外は0を返す
--- mips/trunk/library.c (revision 148)
+++ mips/trunk/library.c (revision 149)
@@ -6,53 +6,107 @@
66 */
77
88 #include <xc.h>
9+#include "main.h"
910 #include "compiler.h"
1011 #include "api.h"
1112 #include "keyinput.h"
13+#include "stdlib.h"
14+#include "math.h"
1215
13-int lib_read(unsigned int label){
14- unsigned int i,code;
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;
1526 static unsigned int pos=0;
1627 static unsigned int in_data=0;
28+ static unsigned char skip=0;
1729 if (label) {
1830 // RESTORE function
19- i=(int)search_label(label);
20- if (!i) {
31+ switch(mode){
32+ case 0:
33+ // label is label data
34+ i=(int)search_label(label);
35+ if (!i) {
36+ err_data_not_found();
37+ return 0;
38+ }
39+ break;
40+ case 1:
41+ // label is pointer
42+ i=label;
43+ break;
44+ case 2:
45+ default:
46+ // Reset data/read
47+ pos=0;
48+ in_data=0;
49+ skip=0;
50+ return 0;
51+ }
52+ i-=(int)(&g_object[0]);
53+ pos=i/4;
54+ in_data=0;
55+ }
56+ // Get data
57+ if (in_data==0) {
58+ for(i=pos;i<g_objpos;i++){
59+ code=g_object[i];
60+ code2=g_object[i+1];
61+ if ((code&0xFFFF0000)!=0x04110000) continue;
62+ // "bgezal zero," assembly found.
63+ // Check if 0x00000020,0x00000021,0x00000022, or 0x00000023 follows
64+ if ((code2&0xfffffffc)!=0x00000020) {// add/addu/sub/subu zero,zero,zero
65+ // If not, skip following block (it's strig).
66+ i+=code&0x0000FFFF;
67+ i--;
68+ continue;
69+ }
70+ // DATA region found.
71+ in_data=(code&0x0000FFFF)-1;
72+ pos=i+2;
73+ skip=code2&0x03;
74+ break;
75+ }
76+ if (g_objpos<=i) {
2177 err_data_not_found();
2278 return 0;
2379 }
24- i-=(int)(&g_object[0]);
25- pos=i/4;
26- return 0;
80+ }
81+ if (label) {
82+ // RESTORE function. Return pointer.
83+ return ((int)&g_object[pos])+skip;
2784 } else {
28- // Get data
29- if (in_data==0) {
30- for(i=pos+1;i<g_objpos;i++){
31- code=g_object[i];
32- if ((code&0xFFFF0000)!=0x04110000) continue;
33- // "bgezal zero," assembly found.
34- // Check if 0x00000021 follows
35- if (g_object[i+1]!=0x00000021) {// addu zero,zero,zero
36- // If not, skip following block (it's strig).
37- i+=code&0x0000FFFF;
38- i--;
39- continue;
85+ switch(mode){
86+ case 0:
87+ // READ() function
88+ in_data--;
89+ return g_object[pos++];
90+ case 1:
91+ default:
92+ // CREAD() function
93+ i=g_object[pos];
94+ i>>=skip*8;
95+ i&=0xff;
96+ if ((++skip)==4) {
97+ skip=0;
98+ in_data--;
99+ pos++;
40100 }
41- // DATA region found.
42- in_data=(code&0x0000FFFF)-1;
43- pos=i+2;
44- break;
45- }
46- if (g_objpos<=i) {
47- err_data_not_found();
48- return 0;
49- }
101+ return i;
50102 }
51- in_data--;
52- return g_object[pos++];
53- }
103+ }
54104 }
55105
106+void reset_dataread(){
107+ lib_read(2,1);
108+}
109+
56110 char* lib_midstr(int var_num, int pos, int len){
57111 int i;
58112 char* str;
@@ -122,21 +176,13 @@
122176 }
123177
124178 int lib_rnd(){
125- int i,j,rnd;
126- rnd=g_rnd_seed;
127- for (i=0;i<15;i++) {
128- j=rnd;
129- j^=(j>>1);
130- j^=(j>>2);
131- j^=(j>>9);
132- j>>=3;
133- j&=0x01;
134- j|=rnd<<1;
135- j&=0x0000FFFF;
136- rnd=j;
137- }
138- g_rnd_seed=rnd;
139- return rnd&0x00007FFF;
179+ int y;
180+ y=g_rnd_seed;
181+ y = y ^ (y << 13);
182+ y = y ^ (y >> 17);
183+ y = y ^ (y << 5);
184+ g_rnd_seed=y;
185+ return y&0x7fff;
140186 }
141187
142188 char* lib_chr(int num){
@@ -332,7 +378,7 @@
332378 while(vkey!=0);
333379 // Get string as a line
334380 lineinput(str,63);
335- if (g_disable_break==0 && (ps2keystatus[0x03] || (PORTB&0x4c80)==0)) err_break();
381+ check_break();
336382 return str;
337383 }
338384
@@ -449,15 +495,356 @@
449495 for(i=0;i<period;i++){
450496 dcount=drawcount;
451497 while(dcount==drawcount){
452- asm ("wait");
453- if (g_disable_break==0 && (ps2keystatus[0x03] || (PORTB&0x4c80)==0)) err_break();
498+ asm (WAIT);
499+ check_break();
454500 }
455501 }
456502 }
457503
504+void allocate_graphic_area(){
505+ if (!g_graphic_area) {
506+ // Use this pointer like unsigned short GVRAM[G_H_WORD*G_Y_RES] __attribute__ ((aligned (4)));
507+ g_graphic_area=(unsigned short*)alloc_memory(G_H_WORD*G_Y_RES/2,ALLOC_GRAPHIC_BLOCK);
508+ // Start graphic and clear screen
509+ init_graphic(g_graphic_area);
510+ // Move current point to (0,0)
511+ g_prev_x=g_prev_y=0;
512+ }
513+}
514+
515+void lib_usegraphic(int mode){
516+ // Modes; 0: stop GRAPHIC, 1: use GRAPHIC, 2: reset GRAPHIC and use it
517+ switch(mode){
518+ case 0:
519+ if (g_use_graphic){
520+ // Stop GRAPHIC if used
521+ set_graphmode(0);
522+ g_use_graphic=0;
523+ // Set timer4 for tempo
524+ PR4=59473; // 3632*262/16-1
525+ } else {
526+ // Prepare GRAPHIC area if not used and not allcated.
527+ allocate_graphic_area();
528+ }
529+ break;
530+ case 2:
531+ // Reset GRAPHIC and use it
532+ g_graphic_area=0;
533+ // Continue to case 1:
534+ case 1:
535+ case 3:
536+ default:
537+ // Use GRAPHIC
538+ allocate_graphic_area();
539+ // Start showing GRAPHIC with mode 1, but not with mode 3
540+ if (mode !=3 && !g_use_graphic){
541+ set_graphmode(1);
542+ g_use_graphic=1;
543+ // Set timer4 for tempo
544+ PR4=55756; // ~=3405*262/16-1(55755.875)
545+ }
546+ break;
547+ }
548+}
549+
550+int lib_graphic(int a0, int a1, int v0){
551+ unsigned char b;
552+ enum functions func=(enum functions)(a0>>24);
553+ int x1=(a0>>12)&0x0FFF;
554+ int y1=a0&0x0FFF;
555+ int x2=(a1>>12)&0x0FFF;
556+ int y2=a1&0x0FFF;
557+ // Disable if graphic area is not defined.
558+ if (!g_graphic_area) return;
559+ // Support 12 bit signed integer.
560+ if (x1&0x0800) x1|=0x0FFFFF000;
561+ if (y1&0x0800) y1|=0x0FFFFF000;
562+ if (x2&0x0800) x2|=0x0FFFFF000;
563+ if (y2&0x0800) y2|=0x0FFFFF000;
564+ // If C is omitted in parameters, use current color.
565+ if (v0==-1) {
566+ v0=g_gcolor;
567+ }
568+ // If X1 or Y1 is -2048 (0xFFFFF800/0x0800), use the previous values.
569+ if (x1==-2048) x1=g_prev_x;
570+ if (y1==-2048) y1=g_prev_y;
571+ switch(func){
572+ case FUNC_POINT:// X1,Y1
573+ g_prev_x=x1;
574+ g_prev_y=y1;
575+ break;
576+ case FUNC_PSET:// X1,Y1[,C]
577+ g_pset(x1,y1,v0&0x0F);
578+ g_prev_x=x1;
579+ g_prev_y=y1;
580+ break;
581+ case FUNC_LINE:// X1,Y1,X2,Y2[,C]
582+ if (y1==y2) g_hline(x1,x2,y1,v0&0x0F);
583+ else g_gline(x1,y1,x2,y2,v0&0x0F);
584+ g_prev_x=x2;
585+ g_prev_y=y2;
586+ break;
587+ case FUNC_BOXFILL:// X1,Y1,X2,Y2[,C]
588+ g_boxfill(x1,y1,x2,y2,v0&0x0F);
589+ g_prev_x=x2;
590+ g_prev_y=y2;
591+ break;
592+ case FUNC_CIRCLE:// X1,Y1,R[,C]
593+ g_circle(x1,y1,x2,v0&0x0F);
594+ g_prev_x=x1;
595+ g_prev_y=y1;
596+ break;
597+ case FUNC_CIRCLEFILL:// X1,Y1,R[,C]
598+ g_circlefill(x1,y1,x2,v0&0x0F);
599+ g_prev_x=x1;
600+ g_prev_y=y1;
601+ break;
602+ case FUNC_GPRINT:// X1,Y1,C,BC,S$
603+ g_printstr(x1,y1,x2,y2,(unsigned char*)v0);
604+ // Move current X,Y according to the string
605+ while(b=((unsigned char*)v0)[0]){
606+ v0++;
607+ if (b==0x0d) {
608+ x1=0;
609+ y1+=8;
610+ } else {
611+ x1+=8;
612+ }
613+ }
614+ g_prev_x=x1;
615+ g_prev_y=y1;
616+ break;
617+ case FUNC_PUTBMP2:// X1,Y1,M,N,BMP(label)
618+ // Search CDATA
619+ // It starts from either 0x00000020,0x00000021,0x00000022, or 0x00000023.
620+ while((((unsigned int*)v0)[0]&0xfffffffc)!=0x00000020) v0+=4;
621+ // CDATA starts from next word.
622+ // MLB 3 bytes show skip byte(s).
623+ v0+=4+(((unsigned int*)v0)[0]&0x03);
624+ // Contunue to FUNC_PUTBMP.
625+ case FUNC_PUTBMP:// X1,Y1,M,N,BMP(pointer)
626+ g_putbmpmn(x1,y1,x2,y2,(const unsigned char*)v0);
627+ g_prev_x=x1;
628+ g_prev_y=y1;
629+ break;
630+ case FUNC_GCOLOR:// (X1,Y1)
631+ v0=g_color(x1,y1);
632+ break;
633+ default:
634+ break;
635+ }
636+ return v0;
637+}
638+
639+void lib_var_push(int* sp,unsigned int flags){
640+ unsigned int strflags=0;
641+ int varnum;
642+ int stack=0;
643+ // Store flags in stack
644+ // Note that sp[1] is used for string return address
645+ sp[2]=flags;
646+ for(varnum=0;varnum<26;varnum++){
647+ if (flags&1) {
648+ sp[(stack++)+4]=g_var_mem[varnum];
649+ if (g_var_size[varnum] && g_var_mem[varnum]==(int)(&g_var_pointer[varnum])) {
650+ // strflags change using varnum
651+ strflags|=1<<varnum;
652+ // Copy to VAR_BLOCK
653+ move_to_perm_block(varnum);
654+ }
655+ // Clear variable
656+ g_var_mem[varnum]=0;
657+ }
658+ flags>>=1;
659+ }
660+ sp[3]=strflags;
661+}
662+void lib_var_pop(int* sp){
663+ // Note that sp is 4 bytes larger than that in lib_var_push
664+ unsigned int flags;
665+ unsigned int strflags;
666+ int varnum;
667+ int stack=0;
668+ flags=sp[1];
669+ strflags=sp[2];
670+ for(varnum=0;varnum<26;varnum++){
671+ if (flags&1) {
672+ g_var_mem[varnum]=sp[(stack++)+3];
673+ if (strflags&1) {
674+ // Restore from VAR_BLOCK
675+ move_from_perm_block(varnum);
676+ }
677+ }
678+ flags>>=1;
679+ strflags>>=1;
680+ }
681+}
682+
683+int lib_system(int a0,int v0){
684+ switch(a0){
685+ // Version info
686+ case 0: return (int)SYSVER1;
687+ case 1: return (int)SYSVER2;
688+ case 2: return (int)BASVER;
689+ case 3: return (int)FILENAME_FLASH_ADDRESS;
690+ // Display info
691+ case 20: return WIDTH_X;
692+ case 21: return WIDTH_Y;
693+ case 22: return G_X_RES;
694+ case 23: return G_Y_RES;
695+ case 24: return cursorcolor;
696+ case 25: return g_gcolor;
697+ case 26: return ((int)(cursor-TVRAM))%WIDTH_X;
698+ case 27: return ((int)(cursor-TVRAM))/WIDTH_X;
699+ case 28: return g_prev_x;
700+ case 29: return g_prev_y;
701+ // Keyboard info
702+ case 40: return (int)inPS2MODE();
703+ case 41: return (int)vkey;
704+ case 42: return (int)lockkey;
705+ case 43: return (int)keytype;
706+ // Pointers to gloval variables
707+ case 100: return (int)&g_var_mem[0];
708+ case 101: return (int)&g_rnd_seed;
709+ case 102: return (int)&TVRAM[0];
710+ case 103: return (int)&FontData[0];
711+ case 104: return (int)g_var_mem[ALLOC_PCG_BLOCK];
712+ case 105: return (int)g_var_mem[ALLOC_GRAPHIC_BLOCK];
713+ // Change system settings
714+ case 200:
715+ // ON/OFF monitor
716+ if (v0) {
717+ start_composite();
718+ } else {
719+ stop_composite();
720+ }
721+ break;
722+ default:
723+ break;
724+ }
725+ return 0;
726+}
727+
728+char* lib_sprintf(char* format, int data){
729+ char* str;
730+ int i;
731+ char temp[4];
732+ if (!format) format="%g";
733+ i=snprintf((char*)(&temp[0]),4,format,data)+1;
734+ str=alloc_memory((i+3)/4,-1);
735+ snprintf(str,i,format,data);
736+ return str;
737+}
738+
739+int lib_floatfuncs(int ia0,int iv0,enum functions a1){
740+ volatile float a0,v0;
741+ ((int*)(&a0))[0]=ia0;
742+ ((int*)(&v0))[0]=iv0;
743+ switch(a1){
744+ case FUNC_FLOAT:
745+ v0=(float)iv0;
746+ break;
747+ case FUNC_INT:
748+ return (int)v0;
749+ case FUNC_VALSHARP:
750+ v0=strtof((const char*)iv0,0);
751+ break;
752+ case FUNC_SIN:
753+ v0=sinf(v0);
754+ break;
755+ case FUNC_COS:
756+ v0=cosf(v0);
757+ break;
758+ case FUNC_TAN:
759+ v0=tanf(v0);
760+ break;
761+ case FUNC_ASIN:
762+ v0=asinf(v0);
763+ break;
764+ case FUNC_ACOS:
765+ v0=acosf(v0);
766+ break;
767+ case FUNC_ATAN:
768+ v0=atanf(v0);
769+ break;
770+ case FUNC_SINH:
771+ v0=sinhf(v0);
772+ break;
773+ case FUNC_COSH:
774+ v0=coshf(v0);
775+ break;
776+ case FUNC_TANH:
777+ v0=tanhf(v0);
778+ break;
779+ case FUNC_EXP:
780+ v0=expf(v0);
781+ break;
782+ case FUNC_LOG:
783+ v0=logf(v0);
784+ break;
785+ case FUNC_LOG10:
786+ v0=log10f(v0);
787+ break;
788+ case FUNC_POW:
789+ v0=powf(v0,a0);
790+ break;
791+ case FUNC_SQRT:
792+ v0=sqrtf(v0);
793+ break;
794+ case FUNC_CEIL:
795+ v0=ceilf(v0);
796+ break;
797+ case FUNC_FLOOR:
798+ v0=floorf(v0);
799+ break;
800+ case FUNC_FABS:
801+ v0=fabsf(v0);
802+ break;
803+ case FUNC_MODF:
804+ v0=modff(v0,(void*)&a0);
805+ break;
806+ case FUNC_FMOD:
807+ v0=fmodf(v0,a0);
808+ break;
809+ default:
810+ err_unknown();
811+ break;
812+ }
813+ return ((int*)(&v0))[0];
814+};
815+
816+int* lib_dim(int varnum, int argsnum, int* sp){
817+ int i,j;
818+ static int* heap;
819+ // Calculate total length.
820+ int len=0; // Total length
821+ int size=1; // Size of current block
822+ for(i=1;i<=argsnum;i++){
823+ size*=sp[i]+1;
824+ len+=size;
825+ }
826+ // Allocate memory
827+ heap=calloc_memory(len,varnum);
828+ // Construct pointers
829+ len=0;
830+ size=1;
831+ for(i=1;i<argsnum;i++){
832+ size*=sp[i]+1;
833+ for(j=0;j<size;j++){
834+ heap[len+j]=(int)&heap[len+size+(sp[i+1]+1)*j];
835+ }
836+ len+=size;
837+ }
838+ return heap;
839+};
840+
458841 int _call_library(int a0,int a1,int a2,enum libs a3);
459842
460843 void call_library(void){
844+ // Store s6 in g_s6
845+ asm volatile("la $a2,%0"::"i"(&g_s6));
846+ asm volatile("sw $s6,0($a2)");
847+ // Copy $v0 to $a2 as 3rd argument of function
461848 asm volatile("addu $a2,$v0,$zero");
462849 asm volatile("j _call_library");
463850 }
@@ -465,11 +852,12 @@
465852 int _call_library(int a0,int a1,int v0,enum libs a3){
466853 // usage: call_lib_code(LIB_XXXX);
467854 // Above code takes 2 words.
468- if (g_disable_break==0 && (ps2keystatus[0x03] || (PORTB&0x4c80)==0)) err_break();
855+ check_break();
469856 switch(a3){
470- case LIB_DIV0:
471- err_div_zero();
472- return;
857+ case LIB_FLOAT:
858+ return lib_float(a0,v0,(enum operator)a1); // see operator.c
859+ case LIB_FLOATFUNCS:
860+ return lib_floatfuncs(a0,v0,(enum functions)a1);
473861 case LIB_STRNCMP:
474862 return strncmp((char*)a0,(char*)a1,v0);
475863 case LIB_MIDSTR:
@@ -491,13 +879,23 @@
491879 return (int)lib_connect_string((char*)a0, (char*)v0);
492880 case LIB_STRING:
493881 lib_string(a0);
494- return;
882+ return v0;
495883 case LIB_PRINTSTR:
496884 printstr((char*)v0);
497- return;
885+ return v0;
886+ case LIB_GRAPHIC:
887+ return lib_graphic(a0,a1,v0);
888+ case LIB_SPRINTF:
889+ return (int)lib_sprintf((char*)v0,a0);
890+ case LIB_VAR_PUSH:
891+ lib_var_push((int*)a1,a0);
892+ return v0;
893+ case LIB_VAR_POP:
894+ lib_var_pop((int*)a1);
895+ return v0;
498896 case LIB_SCROLL:
499897 lib_scroll(a0,v0);
500- return;
898+ return v0;
501899 case LIB_KEYS:
502900 return lib_keys(v0);
503901 case LIB_INKEY:
@@ -504,56 +902,83 @@
504902 return (int)lib_inkey(v0);
505903 case LIB_CURSOR:
506904 setcursor(a0,v0,cursorcolor);
507- return;
905+ return v0;
508906 case LIB_SOUND:
509907 set_sound((unsigned long*)v0);
510- return;
908+ return v0;
511909 case LIB_MUSICFUNC:
512910 return musicRemaining();
513911 case LIB_MUSIC:
514912 set_music((char*)v0);
515- return;
913+ return v0;
516914 case LIB_SETDRAWCOUNT:
517915 drawcount=(v0&0x0000FFFF);
518- return;
916+ return v0;
519917 case LIB_DRAWCOUNT:
520918 return drawcount;
919+ case LIB_SYSTEM:
920+ return lib_system(a0,v0);
521921 case LIB_RESTORE:
522- lib_read(v0);
523- return;
922+ return lib_read(0,v0);
923+ case LIB_RESTORE2:
924+ return lib_read(1,v0);
524925 case LIB_READ:
525- return lib_read(0);
926+ return lib_read(0,0);
927+ case LIB_CREAD:
928+ return lib_read(1,0);
526929 case LIB_LABEL:
527930 return (int)lib_label(v0);
528931 case LIB_INPUT:
529932 return (int)lib_input();
933+ case LIB_USEGRAPHIC:
934+ lib_usegraphic(v0);
935+ return v0;
530936 case LIB_USEPCG:
531937 lib_usepcg(v0);
532- return;
938+ return v0;
533939 case LIB_PCG:
534940 lib_pcg(a0,a1,v0);
535- return;
941+ return v0;
536942 case LIB_BGCOLOR: // BGCOLOR R,G,B
537943 set_bgcolor(v0,a0,a1); //set_bgcolor(b,r,g);
538- return;
944+ return v0;
539945 case LIB_PALETTE: // PALETTE N,R,G,B
540946 set_palette(a0,v0,(a1>>16)&255,a1&255); // set_palette(n,b,r,g);
541- return;
947+ return v0;
948+ case LIB_GPALETTE:// GPALETTE N,R,G,B
949+ if (g_graphic_area) g_set_palette(a0,v0,(a1>>16)&255,a1&255); // g_set_palette(n,b,r,g);
950+ return v0;
542951 case LIB_CLS:
543952 clearscreen();
544- return;
953+ return v0;
954+ case LIB_GCLS:
955+ if (g_graphic_area) g_clearscreen();
956+ g_prev_x=g_prev_y=0;
957+ return v0;
545958 case LIB_COLOR:
546959 setcursorcolor(v0);
547- return;
960+ return v0;
961+ case LIB_GCOLOR:
962+ g_gcolor=v0;
963+ return v0;
548964 case LIB_WAIT:
549965 lib_wait(v0);
550- return;
966+ return v0;
551967 case LIB_CLEAR:
552968 lib_clear();
553- return;
969+ return v0;
554970 case LIB_DIM:
555- return (int)calloc_memory(v0+1, a0);
971+ return (int)lib_dim(a0,a1,(int*)v0);
972+#ifdef __DEBUG
973+ case LIB_DEBUG:
974+ asm volatile("nop");
975+ return v0;
976+#endif
977+ case LIB_DIV0:
978+ err_div_zero();
979+ return v0;
556980 default:
557- break;
981+ err_unknown();
982+ return v0;
558983 }
559984 }
\ No newline at end of file
--- mips/trunk/string.c (revision 148)
+++ mips/trunk/string.c (revision 149)
@@ -7,7 +7,8 @@
77
88 /*
99 Public functions:
10- char* teg_string(void);
10+ char* get_string(void);
11+ char* simple_string(void);
1112 */
1213
1314 #include "api.h"
@@ -15,7 +16,7 @@
1516
1617 char* simple_string(void){
1718 char* err;
18- char b1,b2;
19+ unsigned char b1,b2;
1920 int i,j;
2021 next_position();
2122 b1=g_source[g_srcpos];
@@ -23,8 +24,21 @@
2324 if (b1=='"') {
2425 // Constant string
2526 // Count character number (+1 for \0)
26- for(i=1;g_source[g_srcpos+i]!='"';i++);
27- g_srcpos++;;
27+ // This may be more than actual character number due to escape sequence.
28+ i=0;
29+ while(1){
30+ i++;
31+ b1=g_source[g_srcpos+i];
32+ if (b1=='"') {
33+ break;
34+ } else if (b1=='\\') {
35+ i++;
36+ } else if (b1<0x20) {
37+ // This is an error, that will be detected later again.
38+ break;
39+ }
40+ };
41+ g_srcpos++;
2842 // Determine required word number
2943 i=(i+3)/4;
3044 // Determine address containing the string
@@ -34,9 +48,30 @@
3448 check_obj_space(2+i);
3549 g_object[g_objpos++]=0x04110000|((i+1)&0x0000FFFF); // bgezal zero,xxxx
3650 g_object[g_objpos++]=0x03E01021; // addu v0,ra,zero
37-
38-
3951 for(j=0;(b1=g_source[g_srcpos++])!='"';j++) {
52+ if (b1=='\\') {
53+ b1=g_source[g_srcpos++];
54+ if (b1=='x' || b1=='X') {
55+ // Hexadecimal
56+ b1=g_source[g_srcpos++];
57+ if ('0'<=b1 && b1<='9') b1=b1-'0';
58+ else if ('A'<=b1 && b1<='F') b1=b1-'A'+10;
59+ else if ('a'<=b1 && b1<='f') b1=b1-'a'+10;
60+ else return ERR_SYNTAX;
61+ b2=g_source[g_srcpos++];
62+ if ('0'<=b2 && b2<='9') b2=b2-'0';
63+ else if ('A'<=b2 && b2<='F') b2=b2-'A'+10;
64+ else if ('a'<=b2 && b2<='f') b2=b2-'a'+10;
65+ else return ERR_SYNTAX;
66+ b1=(b1<<4)|b2;
67+ } else if (b1<0x20) {
68+ return ERR_SYNTAX;
69+ } else {
70+ // \\ or \"
71+ }
72+ } else if (b1<0x20) {
73+ return ERR_SYNTAX;
74+ }
4075 ((char*)(&g_object[g_objpos]))[j]=b1;
4176 }
4277 ((char*)(&g_object[g_objpos]))[j]=0x00;
@@ -72,6 +107,8 @@
72107 g_sdepth-=4;
73108 if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
74109 g_srcpos++;
110+ // Temp area will be used when executing.
111+ g_temp_area_used=1;
75112 } else {
76113 return ERR_SYNTAX;
77114 }
@@ -89,7 +126,11 @@
89126 // Function
90127 // String would be pointed by $v0
91128 // Otherwise, it will be assinged in xxx_function() function.
92- return str_function();
129+ err=str_function();
130+ if (err) return err;
131+ // Temp area would be used when executing.
132+ g_temp_area_used=1;
133+ return 0;
93134 } else {
94135 return ERR_SYNTAX;
95136 }
@@ -123,6 +164,8 @@
123164 check_obj_space(2);
124165 g_object[g_objpos++]=0x8FA40000|g_sdepth; // lw a0,xx(sp)
125166 call_lib_code(LIB_CONNECT_STRING);
167+ // Temp area will be used when executing.
168+ g_temp_area_used=1;
126169 // Check if further connection operator exists
127170 next_position();
128171 b1=g_source[g_srcpos];
@@ -164,6 +207,7 @@
164207 g_object[g_objpos++]=0x27BD0000 | g_maxsdepth & 0x0000FFFF; // addiu sp,sp,xx
165208 }
166209 }
210+ g_lastvar=VAR_STRING;
167211 return 0;
168212 }
169213
--- mips/trunk/value.c (revision 148)
+++ mips/trunk/value.c (revision 149)
@@ -14,6 +14,37 @@
1414 char* get_value();
1515 char* get_value_sub(int pr);
1616
17+char* get_dim_value(char b1){
18+ char* err;
19+ err=get_value_sub(priority(OP_VOID));
20+ if (err) return err;
21+ check_obj_space(4);
22+ g_object[g_objpos++]=0x00021080; // sll v0,v0,0x2
23+ g_object[g_objpos++]=0x8FC30000|((b1-'A')*4); // lw v1,xx(s8)
24+ g_object[g_objpos++]=0x00621821; // addu v1,v1,v0
25+ g_object[g_objpos++]=0x8C620000; // lw v0,0(v1)
26+ next_position();
27+ if (g_source[g_srcpos]==','){
28+ // 2D, 3D or more
29+ check_obj_space(2);
30+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
31+ do {
32+ g_srcpos++;
33+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
34+ err=get_value_sub(priority(OP_VOID));
35+ if (err) return err;
36+ check_obj_space(5);
37+ g_object[g_objpos++]=0x00021080; // sll v0,v0,0x2
38+ g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp)
39+ g_object[g_objpos++]=0x00621821; // addu v1,v1,v0
40+ g_object[g_objpos++]=0x8C620000; // lw v0,0(v1)
41+ } while (g_source[g_srcpos]==',');
42+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
43+ }
44+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
45+ g_srcpos++;
46+ return 0;
47+}
1748
1849 char* get_simple_value(void){
1950 int i;
@@ -39,6 +70,7 @@
3970 if (err) return err;
4071 check_obj_space(1);
4172 g_object[g_objpos++]=0x00021023; // subu v0,zero,v0
73+ g_intconst=-g_intconst;
4274 } else {
4375 // Main routine of getting value here
4476 if (b1=='+') g_srcpos++; // Ignore unary '+' operator
@@ -63,6 +95,7 @@
6395 }
6496 g_srcpos++;
6597 }
98+ g_intconst=i;
6699 if (i&0xFFFF0000) {
67100 // 32 bit
68101 check_obj_space(2);
@@ -73,36 +106,23 @@
73106 check_obj_space(1);
74107 g_object[g_objpos++]=0x34020000|(i&0x0000FFFF); // ori v0,zero,xxxx
75108 }
76- } else if ('0'<=b1 && b1<='9' || b1=='-' && '0'<=b2 && b2<='9') {
77- if (b1=='-') {
78- // Starts with '-'
79- // Decimal number, negative
109+ } else if ('0'<=b1 && b1<='9') {
110+ // Starts with 0-9
111+ // Decimal number
112+ i=0;
113+ while(b1=g_source[g_srcpos]) {
114+ if ('0'<=b1 && b1<='9') {
115+ i*=10;
116+ i+=b1-'0';
117+ } else {
118+ break;
119+ }
80120 g_srcpos++;
81- i=0;
82- while(b1=g_source[g_srcpos]) {
83- if ('0'<=b1 && b1<='9') {
84- i*=10;
85- i+=b1-'0';
86- } else {
87- break;
88- }
89- g_srcpos++;
90- }
91- i=0-i;
92- } else {
93- // Starts with 0-9
94- // Decimal number
95- i=0;
96- while(b1=g_source[g_srcpos]) {
97- if ('0'<=b1 && b1<='9') {
98- i*=10;
99- i+=b1-'0';
100- } else {
101- break;
102- }
103- g_srcpos++;
104- }
105121 }
122+ // The next character should not be '.' or 'E'.
123+ // Or, it must be recognized as a float value.
124+ if (b1=='.' || b1=='E') return ERR_SYNTAX;
125+ g_intconst=i;
106126 if (i&0xFFFF0000) {
107127 // 32 bit
108128 check_obj_space(2);
@@ -113,33 +133,27 @@
113133 check_obj_space(1);
114134 g_object[g_objpos++]=0x34020000|(i&0x0000FFFF); // ori v0,zero,xxxx
115135 }
116- } else if ('A'<=b1 && b1<='Z' && b2=='(') {
117- // A( - Z(
118- // Dimension
119- g_srcpos++;
120- g_srcpos++;
121- err=get_value_sub(priority(OP_VOID));
122- if (err) return err;
123- next_position();
124- if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
125- g_srcpos++;
126- check_obj_space(4);
127- g_object[g_objpos++]=0x00021080; // sll v0,v0,0x2
128- g_object[g_objpos++]=0x8FC30000|((b1-'A')*4); // lw v1,xx(s8)
129- g_object[g_objpos++]=0x00621821; // addu v1,v1,v0
130- g_object[g_objpos++]=0x8C620000; // lw v0,0(v1)
131- } else if ('A'<=b1 && b1<='Z' && (b2<'A' || 'Z'<b2)) {
132- // A-Z
133- // Simple value
134- g_srcpos++;
135- check_obj_space(1);
136- g_object[g_objpos++]=0x8FC20000|((b1-'A')*4); // lw v0,xx(s8)
137- } else if ('A'<=b1 && b1<='Z') {
138- // Starts with A-Z
139- // Functions
140- return function();
141136 } else {
142- return ERR_SYNTAX;
137+ g_valueisconst=0;
138+ if ('A'<=b1 && b1<='Z' && b2=='(') {
139+ // A( - Z(
140+ // Dimension
141+ g_srcpos++;
142+ g_srcpos++;
143+ return get_dim_value(b1);
144+ } else if ('A'<=b1 && b1<='Z' && (b2<'A' || 'Z'<b2) && b2!='#' && b2!='$') {
145+ // A-Z
146+ // Simple value
147+ g_srcpos++;
148+ check_obj_space(1);
149+ g_object[g_objpos++]=0x8FC20000|((b1-'A')*4); // lw v0,xx(s8)
150+ } else if ('A'<=b1 && b1<='Z') {
151+ // Starts with A-Z
152+ // Functions
153+ return function();
154+ } else {
155+ return ERR_SYNTAX;
156+ }
143157 }
144158 }
145159 // No error
@@ -212,5 +226,46 @@
212226 g_object[g_objpos++]=0x27BD0000 | g_maxsdepth & 0x0000FFFF; // addiu sp,sp,xx
213227 }
214228 }
229+ g_lastvar=VAR_INTEGER;
215230 return 0;
216-}
\ No newline at end of file
231+}
232+
233+char* get_floatOrValue(){
234+ char* err;
235+ char b;
236+ int opos,spos,sdpt;
237+ sdpt=g_sdepth;
238+ opos=g_objpos;
239+ spos=g_srcpos;
240+ // First try integer.
241+ // Integer value has the higher priolity than float value.
242+ err=get_value();
243+ b=g_source[g_srcpos];
244+ if (err) {
245+ // Value is not integer. Let's try float.
246+ g_sdepth=sdpt;
247+ g_objpos=opos;
248+ g_srcpos=spos;
249+ return get_float();
250+ } else {
251+ // Value was recognized as an integer.
252+ return 0;
253+ }
254+}
255+
256+char* get_stringFloatOrValue(){
257+ char* err;
258+ int opos,spos;
259+ opos=g_objpos;
260+ spos=g_srcpos;
261+ // First try string, float, then integer.
262+ err=get_string();
263+ if (err) {
264+ g_objpos=opos;
265+ g_srcpos=spos;
266+ return get_floatOrValue();
267+ } else {
268+ return 0;
269+ }
270+}
271+