BASIC compiler/interpreter for PIC32MX/MZ-80K (suspended)
| Revision | 149 (tree) |
|---|---|
| Time | 2016-08-05 03:39:28 |
| Author | kmorimatsu |
Update trunk with MachiKania type Z ver 1.00
| @@ -7,7 +7,7 @@ | ||
| 7 | 7 | |
| 8 | 8 | #include <xc.h> |
| 9 | 9 | #include "compiler.h" |
| 10 | -#include "colortext32.h" | |
| 10 | +#include "api.h" | |
| 11 | 11 | |
| 12 | 12 | /* |
| 13 | 13 | Timer3: 1/32 prescaler, toggle mode : 894886.25 Hz |
| @@ -166,8 +166,8 @@ | ||
| 166 | 166 | T3CON=0x0050; // Prescaller: 1:32 (1.8 MHz), not yet started |
| 167 | 167 | |
| 168 | 168 | // 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 | |
| 171 | 171 | // Timer 4 interruption, IPL3 |
| 172 | 172 | IPC4bits.T4IP=3; |
| 173 | 173 | IPC4bits.T4IS=0; |
| @@ -348,7 +348,7 @@ | ||
| 348 | 348 | g_soundrepeat=g_soundstart=g_soundend=0; |
| 349 | 349 | pos=0; |
| 350 | 350 | do { |
| 351 | - while(data[1]!=0x00000021) data++; // Seek DATA statement | |
| 351 | + while(data[1]!=0x00000020) data++; // Seek DATA statement | |
| 352 | 352 | datalen=(data[0]&0x00007FFF)-1; // Use bgezal statement containing data length. |
| 353 | 353 | data+=2; |
| 354 | 354 | while(0<datalen){ |
| @@ -357,6 +357,12 @@ | ||
| 357 | 357 | sound=data[0]&0x0000FFFF; |
| 358 | 358 | data++; |
| 359 | 359 | 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 | + } | |
| 360 | 366 | g_sound[pos]=sound-1; |
| 361 | 367 | g_soundlen[pos]=len; |
| 362 | 368 | pos++; |
| @@ -452,6 +458,12 @@ | ||
| 452 | 458 | g_mspos++; |
| 453 | 459 | len=len/musicGetNum(); |
| 454 | 460 | } |
| 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 | + } | |
| 455 | 467 | // Update music value array |
| 456 | 468 | IEC0bits.T4IE=0; // Stop interruption, first. |
| 457 | 469 | if (g_musicstart==g_musicend) { |
| @@ -18,7 +18,16 @@ | ||
| 18 | 18 | return 0; |
| 19 | 19 | } |
| 20 | 20 | |
| 21 | +char* cread_function(){ | |
| 22 | + call_lib_code(LIB_CREAD); | |
| 23 | + return 0; | |
| 24 | +} | |
| 25 | + | |
| 21 | 26 | 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; | |
| 22 | 31 | return gosub_statement(); |
| 23 | 32 | } |
| 24 | 33 | char* strncmp_function(){ |
| @@ -227,6 +236,202 @@ | ||
| 227 | 236 | return 0; |
| 228 | 237 | } |
| 229 | 238 | |
| 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 | + | |
| 230 | 435 | char* str_function(void){ |
| 231 | 436 | char* err; |
| 232 | 437 | if (nextCodeIs("CHR$(")) { |
| @@ -237,6 +442,18 @@ | ||
| 237 | 442 | err=dec_function(); |
| 238 | 443 | } else if (nextCodeIs("INPUT$(")) { |
| 239 | 444 | 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(); | |
| 240 | 457 | } else { |
| 241 | 458 | return ERR_SYNTAX; |
| 242 | 459 | } |
| @@ -260,6 +477,8 @@ | ||
| 260 | 477 | err=keys_function(); |
| 261 | 478 | } else if (nextCodeIs("READ(")) { |
| 262 | 479 | err=read_function(); |
| 480 | + } else if (nextCodeIs("CREAD(")) { | |
| 481 | + err=cread_function(); | |
| 263 | 482 | } else if (nextCodeIs("GOSUB(")) { |
| 264 | 483 | err=gosub_function(); |
| 265 | 484 | } else if (nextCodeIs("STRNCMP(")) { |
| @@ -280,6 +499,14 @@ | ||
| 280 | 499 | err=val_function(); |
| 281 | 500 | } else if (nextCodeIs("INKEY(")) { |
| 282 | 501 | 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); | |
| 283 | 510 | } else { |
| 284 | 511 | return ERR_SYNTAX; |
| 285 | 512 | } |
| @@ -288,18 +515,3 @@ | ||
| 288 | 515 | g_srcpos++; |
| 289 | 516 | return err; |
| 290 | 517 | } |
| 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 | -//*/ |
| @@ -1,14 +1,16 @@ | ||
| 1 | 1 | /* |
| 2 | 2 | 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 | |
| 4 | 5 | http://hp.vector.co.jp/authors/VA016157/ |
| 5 | - kmorimatsu@users.sourceforge.jp | |
| 6 | 6 | */ |
| 7 | 7 | |
| 8 | 8 | #include "compiler.h" |
| 9 | +#include "main.h" | |
| 9 | 10 | |
| 10 | -// Contain the valus of $gp (GPR of MIPS32) | |
| 11 | +// Contain the valus of $gp and $s6 (GPR of MIPS32) | |
| 11 | 12 | int g_gp; |
| 13 | +int g_s6; | |
| 12 | 14 | |
| 13 | 15 | // Line data when compiling |
| 14 | 16 | int g_line; |
| @@ -23,6 +25,14 @@ | ||
| 23 | 25 | int g_sdepth; |
| 24 | 26 | int g_maxsdepth; |
| 25 | 27 | |
| 28 | +// Following var shows what type of variable was defined | |
| 29 | +// in compiling the last code. | |
| 30 | +enum variable g_lastvar; | |
| 31 | + | |
| 32 | +// Vars used for handling constant integer | |
| 33 | +int g_intconst; | |
| 34 | +char g_valueisconst; | |
| 35 | + | |
| 26 | 36 | // Global vars associated to RAM |
| 27 | 37 | char* g_source; |
| 28 | 38 | int g_srcpos; |
| @@ -29,7 +39,8 @@ | ||
| 29 | 39 | int* g_object; |
| 30 | 40 | int g_objpos; |
| 31 | 41 | 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))); | |
| 33 | 44 | |
| 34 | 45 | // Global area for vars A-Z and three temporary string pointers |
| 35 | 46 | int g_var_mem[ALLOC_BLOCK_NUM]; |
| @@ -36,6 +47,9 @@ | ||
| 36 | 47 | unsigned short g_var_pointer[ALLOC_BLOCK_NUM]; |
| 37 | 48 | unsigned short g_var_size[ALLOC_BLOCK_NUM]; |
| 38 | 49 | |
| 50 | +// Flag to use temporary area when compiling | |
| 51 | +char g_temp_area_used; | |
| 52 | + | |
| 39 | 53 | // Heap area |
| 40 | 54 | int* g_heap_mem; |
| 41 | 55 | int g_max_mem; |
| @@ -48,3 +62,10 @@ | ||
| 48 | 62 | |
| 49 | 63 | // Font data used for PCG |
| 50 | 64 | unsigned char* g_pcg_font; |
| 65 | + | |
| 66 | +// Use or do not use graphic | |
| 67 | +char g_use_graphic; | |
| 68 | + | |
| 69 | +// Pointer to graphic RAM | |
| 70 | +unsigned short* g_graphic_area; | |
| 71 | + |
| @@ -9,13 +9,8 @@ | ||
| 9 | 9 | #include "api.h" |
| 10 | 10 | #include "compiler.h" |
| 11 | 11 | #include "editor.h" |
| 12 | +#include "main.h" | |
| 12 | 13 | |
| 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 | - | |
| 19 | 14 | char* printdec(int num){ |
| 20 | 15 | char str[11]; |
| 21 | 16 | int i; |
| @@ -67,11 +62,14 @@ | ||
| 67 | 62 | return -1; |
| 68 | 63 | } |
| 69 | 64 | |
| 65 | + // Initialize parameters | |
| 70 | 66 | g_pcg_font=0; |
| 71 | - g_rnd_seed=0x3045; | |
| 67 | + g_use_graphic=0; | |
| 68 | + g_graphic_area=0; | |
| 72 | 69 | clearscreen(); |
| 73 | - setcursor(0,0,7); | |
| 74 | - printstr("BASIC KM-1120\n"); | |
| 70 | + setcursor(0,0,7); | |
| 71 | + | |
| 72 | + printstr("BASIC "BASVER"\n"); | |
| 75 | 73 | wait60thsec(15); |
| 76 | 74 | // Initialize music |
| 77 | 75 | init_music(); |
| @@ -80,7 +78,7 @@ | ||
| 80 | 78 | |
| 81 | 79 | // Compile the file |
| 82 | 80 | err=compile_file(); |
| 83 | - FSfclose(g_fhandle); | |
| 81 | + close_file(); | |
| 84 | 82 | if (err) { |
| 85 | 83 | // Compile error |
| 86 | 84 | printstr(err); |
| @@ -112,6 +110,21 @@ | ||
| 112 | 110 | if(test) return 0; //コンパイルのみの場合 |
| 113 | 111 | wait60thsec(15); |
| 114 | 112 | |
| 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 | + | |
| 115 | 128 | // Assign memory |
| 116 | 129 | set_free_area((void*)(g_object+g_objpos),(void*)(&RAM[RAMSIZE])); |
| 117 | 130 | // Execute program |
| @@ -119,6 +132,8 @@ | ||
| 119 | 132 | // Work area (used for A-Z values) is next to the object code area. |
| 120 | 133 | start_program((void*)(&(RAM[0])),(void*)(&g_var_mem[0])); |
| 121 | 134 | printstr("\nOK\n"); |
| 135 | + set_graphmode(0); | |
| 136 | + g_use_graphic=0; | |
| 122 | 137 | |
| 123 | 138 | return 0; |
| 124 | 139 | } |
| @@ -8,6 +8,18 @@ | ||
| 8 | 8 | #include "api.h" |
| 9 | 9 | #include "compiler.h" |
| 10 | 10 | |
| 11 | +char* rem_statement(){ | |
| 12 | + if (g_source[g_srcpos-4]<0x20) { | |
| 13 | + // This line contains only "REM" statement | |
| 14 | + // Delete $s6-setting command if exists. | |
| 15 | + if ((g_object[g_objpos-1]&0xffff0000)==0x34160000) g_objpos--; | |
| 16 | + } | |
| 17 | + while(0x20<=g_source[g_srcpos]){ | |
| 18 | + g_srcpos++; | |
| 19 | + } | |
| 20 | + return 0; | |
| 21 | +} | |
| 22 | + | |
| 11 | 23 | char* sound_statement(){ |
| 12 | 24 | char *err; |
| 13 | 25 | err=get_label(); |
| @@ -42,21 +54,13 @@ | ||
| 42 | 54 | b1=g_source[g_srcpos]; |
| 43 | 55 | while('0'<=b1 && b1<='9' || b1=='-' || b1=='$'){ |
| 44 | 56 | prevpos=g_objpos; |
| 57 | + g_valueisconst=1; | |
| 45 | 58 | err=get_simple_value(); |
| 59 | + if (!g_valueisconst) err=ERR_SYNTAX; | |
| 46 | 60 | 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); | |
| 58 | 62 | g_objpos=prevpos; |
| 59 | - g_object[g_objpos++]=i; | |
| 63 | + g_object[g_objpos++]=g_intconst; | |
| 60 | 64 | next_position(); |
| 61 | 65 | b1=g_source[g_srcpos]; |
| 62 | 66 | if (b1!=',') break; |
| @@ -63,26 +67,123 @@ | ||
| 63 | 67 | g_srcpos++; |
| 64 | 68 | next_position(); |
| 65 | 69 | 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 | + } | |
| 66 | 81 | } |
| 67 | 82 | return 0; |
| 68 | 83 | } |
| 69 | 84 | |
| 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; | |
| 73 | 89 | char* err; |
| 74 | - prevpos=g_objpos; | |
| 90 | + char b1; | |
| 91 | + char* cpy; | |
| 92 | + int shift=0; | |
| 93 | + int i=0; | |
| 94 | + beginpos=g_objpos; | |
| 75 | 95 | check_obj_space(2); |
| 76 | 96 | 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 | + } | |
| 80 | 144 | // 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 | |
| 83 | 148 | return 0; |
| 84 | 149 | } |
| 85 | 150 | |
| 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 | + | |
| 86 | 187 | char* clear_statement(){ |
| 87 | 188 | call_lib_code(LIB_CLEAR); |
| 88 | 189 | return 0; |
| @@ -109,26 +210,44 @@ | ||
| 109 | 210 | char* dim_statement(){ |
| 110 | 211 | char* err; |
| 111 | 212 | char b1; |
| 213 | + int spos; | |
| 214 | + int stack; | |
| 112 | 215 | while(1){ |
| 216 | + stack=0; | |
| 113 | 217 | next_position(); |
| 114 | 218 | b1=g_source[g_srcpos]; |
| 115 | 219 | if (b1<'A' || 'Z'<b1) return ERR_SYNTAX; |
| 116 | 220 | g_srcpos++; |
| 221 | + if (g_source[g_srcpos]=='#') g_srcpos++; | |
| 117 | 222 | next_position(); |
| 118 | 223 | 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]==','); | |
| 122 | 234 | if (g_source[g_srcpos]!=')') return ERR_SYNTAX; |
| 123 | 235 | 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 | |
| 126 | 240 | 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 | |
| 127 | 246 | next_position(); |
| 128 | 247 | if (g_source[g_srcpos]!=',') break; |
| 129 | 248 | g_srcpos++; |
| 130 | 249 | } |
| 131 | - return 0; | |
| 250 | + return 0; | |
| 132 | 251 | } |
| 133 | 252 | |
| 134 | 253 | char* label_statement(){ |
| @@ -157,16 +276,11 @@ | ||
| 157 | 276 | if (err) return err; |
| 158 | 277 | if (g_label) { |
| 159 | 278 | // 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 | |
| 170 | 284 | } else { |
| 171 | 285 | // Dynamic number |
| 172 | 286 | err=get_value(); |
| @@ -176,7 +290,7 @@ | ||
| 176 | 290 | return 0; |
| 177 | 291 | } |
| 178 | 292 | |
| 179 | -char* gosub_statement(){ | |
| 293 | +char* gosub_statement_sub(){ | |
| 180 | 294 | char* err; |
| 181 | 295 | err=get_label(); |
| 182 | 296 | if (err) return err; |
| @@ -211,6 +325,50 @@ | ||
| 211 | 325 | return 0; |
| 212 | 326 | } |
| 213 | 327 | |
| 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 | + | |
| 214 | 372 | char* return_statement(){ |
| 215 | 373 | char* err; |
| 216 | 374 | char b1; |
| @@ -218,7 +376,7 @@ | ||
| 218 | 376 | b1=g_source[g_srcpos]; |
| 219 | 377 | if (0x20<b1 && b1!=':') { |
| 220 | 378 | // There is a return value. |
| 221 | - err=get_value(); | |
| 379 | + err=get_stringFloatOrValue(); | |
| 222 | 380 | if (err) return err; |
| 223 | 381 | } |
| 224 | 382 | check_obj_space(3); |
| @@ -255,16 +413,31 @@ | ||
| 255 | 413 | char* err; |
| 256 | 414 | int prevpos,bpos; |
| 257 | 415 | // Get value. |
| 258 | - err=get_value(); | |
| 416 | + err=get_floatOrValue(); | |
| 259 | 417 | if (err) return err; |
| 260 | 418 | // 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 | |
| 262 | 436 | // If $v0=0 then skip. |
| 263 | 437 | bpos=g_objpos; |
| 264 | 438 | check_obj_space(2); |
| 265 | 439 | g_object[g_objpos++]=0x10400000; // beq v0,zero,xxxx |
| 266 | 440 | g_object[g_objpos++]=0x00000000; // nop |
| 267 | - // Next statement is either label or general statement | |
| 268 | 441 | prevpos=g_srcpos; |
| 269 | 442 | if (statement()) { |
| 270 | 443 | // May be label |
| @@ -315,8 +488,61 @@ | ||
| 315 | 488 | return 0; |
| 316 | 489 | } |
| 317 | 490 | |
| 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 | +} | |
| 318 | 514 | |
| 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 | +} | |
| 319 | 530 | |
| 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 | + | |
| 320 | 546 | char* end_statement(void){ |
| 321 | 547 | int i; |
| 322 | 548 | i=(int)&g_end_addr; |
| @@ -328,17 +554,70 @@ | ||
| 328 | 554 | return 0; |
| 329 | 555 | } |
| 330 | 556 | |
| 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 | +}; | |
| 331 | 582 | |
| 332 | 583 | char* let_statement(){ |
| 333 | 584 | char* err; |
| 334 | - char b1,b2; | |
| 585 | + char b1,b2,b3; | |
| 335 | 586 | int i; |
| 336 | 587 | next_position(); |
| 337 | 588 | b1=g_source[g_srcpos]; |
| 338 | 589 | b2=g_source[g_srcpos+1]; |
| 590 | + b3=g_source[g_srcpos+2]; | |
| 339 | 591 | if (b1<'A' || 'Z'<b1) return ERR_SYNTAX; |
| 340 | 592 | 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=='$') { | |
| 342 | 621 | // String |
| 343 | 622 | g_srcpos++; |
| 344 | 623 | next_position(); |
| @@ -352,17 +631,9 @@ | ||
| 352 | 631 | return 0; |
| 353 | 632 | } else if (b2=='(') { |
| 354 | 633 | // 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); | |
| 364 | 635 | g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4 |
| 365 | - g_object[g_objpos++]=0xAFA30004; // sw v1,4(sp) | |
| 636 | + let_dim_sub(b1); | |
| 366 | 637 | next_position(); |
| 367 | 638 | if (g_source[g_srcpos]!='=') return ERR_SYNTAX; |
| 368 | 639 | g_srcpos++; |
| @@ -389,7 +660,7 @@ | ||
| 389 | 660 | char* print_statement(){ |
| 390 | 661 | char* err; |
| 391 | 662 | char b1; |
| 392 | - int i,prevpos; | |
| 663 | + int i; | |
| 393 | 664 | int status=0;// 1:',' 2:';' 0:none |
| 394 | 665 | while(1){ |
| 395 | 666 | next_position(); |
| @@ -396,17 +667,23 @@ | ||
| 396 | 667 | b1=g_source[g_srcpos]; |
| 397 | 668 | if (b1<0x20 || b1==':') break; |
| 398 | 669 | 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; | |
| 410 | 687 | } |
| 411 | 688 | // Call printstr() function |
| 412 | 689 | // First argument is the pointer to string |
| @@ -435,6 +712,14 @@ | ||
| 435 | 712 | } |
| 436 | 713 | return 0; |
| 437 | 714 | } |
| 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 | + | |
| 438 | 723 | char* for_statement(){ |
| 439 | 724 | char* err; |
| 440 | 725 | char b1; |
| @@ -455,10 +740,11 @@ | ||
| 455 | 740 | // 4(sp): Address to return to in "NEXT" statement. |
| 456 | 741 | // Store "TO" value in stack |
| 457 | 742 | 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) | |
| 459 | 744 | g_object[g_objpos++]=0xAFA2000C; // sw v0,12(sp) |
| 460 | 745 | // Check if "STEP" exists |
| 461 | 746 | next_position(); |
| 747 | + g_valueisconst=1; | |
| 462 | 748 | if (nextCodeIs("STEP ")) { |
| 463 | 749 | // "STEP" exists. Get value |
| 464 | 750 | err=get_value(); |
| @@ -467,51 +753,133 @@ | ||
| 467 | 753 | // "STEP" not exist. Use "1". |
| 468 | 754 | check_obj_space(1); |
| 469 | 755 | g_object[g_objpos++]=0x24020001; // addiu v0,zero,1 |
| 756 | + g_intconst=1; | |
| 470 | 757 | } |
| 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) | |
| 476 | 762 | // 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 | |
| 491 | 776 | g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp) |
| 492 | - // label2: | |
| 777 | + break_statement(); // (2 words) | |
| 778 | + // continue: | |
| 493 | 779 | return 0; |
| 494 | 780 | } |
| 495 | 781 | |
| 496 | 782 | char* next_statement(){ |
| 497 | 783 | // 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) | |
| 504 | 790 | return 0; |
| 505 | 791 | } |
| 506 | 792 | |
| 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; | |
| 510 | 825 | } |
| 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) | |
| 511 | 852 | return 0; |
| 512 | 853 | } |
| 513 | 854 | |
| 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 | |
| 515 | 883 | // PALETTE N,R,G,B |
| 516 | 884 | char* err; |
| 517 | 885 | // Get N |
| @@ -547,7 +915,7 @@ | ||
| 547 | 915 | g_object[g_objpos++]=0x8FA4000C; // lw a0,12(sp) |
| 548 | 916 | g_object[g_objpos++]=0x27BD000C; // addiu sp,sp,12 |
| 549 | 917 | // a0=N, a1=(R<<16)|G, v0=B |
| 550 | - call_lib_code(LIB_PALETTE); | |
| 918 | + call_lib_code(lib); | |
| 551 | 919 | return 0; |
| 552 | 920 | } |
| 553 | 921 |
| @@ -604,11 +972,30 @@ | ||
| 604 | 972 | return 0; |
| 605 | 973 | } |
| 606 | 974 | |
| 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 | + | |
| 607 | 989 | char* cls_statement(){ |
| 608 | 990 | call_lib_code(LIB_CLS); |
| 609 | 991 | return 0; |
| 610 | 992 | } |
| 611 | 993 | |
| 994 | +char* gcls_statement(){ | |
| 995 | + call_lib_code(LIB_GCLS); | |
| 996 | + return 0; | |
| 997 | +} | |
| 998 | + | |
| 612 | 999 | char* color_statement(){ |
| 613 | 1000 | char* err; |
| 614 | 1001 | err=get_value(); |
| @@ -617,6 +1004,14 @@ | ||
| 617 | 1004 | return 0; |
| 618 | 1005 | } |
| 619 | 1006 | |
| 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 | + | |
| 620 | 1015 | char* param2_statement(enum libs lib){ |
| 621 | 1016 | char* err; |
| 622 | 1017 | // Get 1st |
| @@ -637,6 +1032,11 @@ | ||
| 637 | 1032 | return 0; |
| 638 | 1033 | } |
| 639 | 1034 | |
| 1035 | +char* system_statement(){ | |
| 1036 | + // SYSTEM X,Y | |
| 1037 | + return param2_statement(LIB_SYSTEM); | |
| 1038 | +} | |
| 1039 | + | |
| 640 | 1040 | char* cursor_statement(){ |
| 641 | 1041 | // CURSOR X,Y |
| 642 | 1042 | return param2_statement(LIB_CURSOR); |
| @@ -643,7 +1043,7 @@ | ||
| 643 | 1043 | } |
| 644 | 1044 | |
| 645 | 1045 | char* scroll_statement(){ |
| 646 | - // CURSOR X,Y | |
| 1046 | + // SCROLL X,Y | |
| 647 | 1047 | return param2_statement(LIB_SCROLL); |
| 648 | 1048 | } |
| 649 | 1049 |
| @@ -662,14 +1062,208 @@ | ||
| 662 | 1062 | call_lib_code(LIB_WAIT); |
| 663 | 1063 | return 0; |
| 664 | 1064 | } |
| 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 | +} | |
| 665 | 1111 | |
| 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 | + | |
| 666 | 1258 | char* statement(void){ |
| 667 | 1259 | char* err; |
| 668 | 1260 | int prevpos; |
| 669 | 1261 | next_position(); |
| 1262 | + // Clear flag for temp area usage. | |
| 1263 | + g_temp_area_used=0; | |
| 670 | 1264 | // Initialize stack handler used for value |
| 671 | 1265 | g_sdepth=g_maxsdepth=0; |
| 672 | - if (nextCodeIs("REM ")) { | |
| 1266 | + if (nextCodeIs("REM")) { | |
| 673 | 1267 | err=rem_statement(); |
| 674 | 1268 | } else if (nextCodeIs("SOUND ")) { |
| 675 | 1269 | err=sound_statement(); |
| @@ -680,17 +1274,25 @@ | ||
| 680 | 1274 | } else if (nextCodeIs("CURSOR ")) { |
| 681 | 1275 | err=cursor_statement(); |
| 682 | 1276 | } 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); | |
| 684 | 1280 | } else if (nextCodeIs("BGCOLOR ")) { |
| 685 | 1281 | err=bgcolor_statement(); |
| 686 | 1282 | } else if (nextCodeIs("CLS")) { |
| 687 | 1283 | err=cls_statement(); |
| 1284 | + } else if (nextCodeIs("GCLS")) { | |
| 1285 | + err=gcls_statement(); | |
| 688 | 1286 | } else if (nextCodeIs("COLOR ")) { |
| 689 | 1287 | err=color_statement(); |
| 1288 | + } else if (nextCodeIs("GCOLOR ")) { | |
| 1289 | + err=gcolor_statement(); | |
| 690 | 1290 | } else if (nextCodeIs("RESTORE ")) { |
| 691 | 1291 | err=restore_statement(); |
| 692 | 1292 | } else if (nextCodeIs("DATA ")) { |
| 693 | 1293 | err=data_statement(); |
| 1294 | + } else if (nextCodeIs("CDATA ")) { | |
| 1295 | + err=cdata_statement(); | |
| 694 | 1296 | } else if (nextCodeIs("LABEL ")) { |
| 695 | 1297 | err=label_statement(); |
| 696 | 1298 | } else if (nextCodeIs("DIM ")) { |
| @@ -701,6 +1303,12 @@ | ||
| 701 | 1303 | err=print_statement(); |
| 702 | 1304 | } else if (nextCodeIs("IF ")) { |
| 703 | 1305 | 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(); | |
| 704 | 1312 | } else if (nextCodeIs("END")) { |
| 705 | 1313 | err=end_statement(); |
| 706 | 1314 | } else if (nextCodeIs("EXEC ")) { |
| @@ -727,6 +1335,42 @@ | ||
| 727 | 1335 | err=scroll_statement(); |
| 728 | 1336 | } else if (nextCodeIs("WAIT ")) { |
| 729 | 1337 | 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 | |
| 730 | 1374 | } else { |
| 731 | 1375 | err=let_statement(); |
| 732 | 1376 | } |
| @@ -733,5 +1377,11 @@ | ||
| 733 | 1377 | if (err) return err; |
| 734 | 1378 | // Stack handler must be zero here. |
| 735 | 1379 | 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 | + } | |
| 736 | 1386 | return 0; |
| 737 | 1387 | } |
| @@ -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 |
| @@ -8,15 +8,19 @@ | ||
| 8 | 8 | #include "compiler.h" |
| 9 | 9 | |
| 10 | 10 | /* |
| 11 | - ALLOC_VAR_NUM: # of variables used for allocation of memory (string/dimension). | |
| 12 | - 0 is for A, 1 is for B, ... , and 25 is for Z. | |
| 13 | - This number also includes temporary area used for string construction etc. | |
| 14 | - Temporary area is cleared every line of BASIC code in alloc_memory(). | |
| 15 | - ALLOC_BLOCK_NUM: # of blocks that can be used for memory allocation. | |
| 16 | - This # also includes the ones for ALLOC_VAR_NUM. | |
| 17 | - After ALLOC_VAR_NUM area, dedicated memory area 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. | |
| 20 | 24 | */ |
| 21 | 25 | |
| 22 | 26 | void set_free_area(void* begin, void* end){ |
| @@ -46,7 +50,8 @@ | ||
| 46 | 50 | asm volatile("bltz $s6,_alloc_memory_main"); // Skip if $s6<0 |
| 47 | 51 | // Following code will be activated after setting $s6 register |
| 48 | 52 | // 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; | |
| 50 | 55 | // Remove all temporary blocks |
| 51 | 56 | // Note that g_var_size is short integer. |
| 52 | 57 | // Note that ALLOC_VAR_NUM is used here (but not ALLOC_BLOC_NUM) |
| @@ -61,7 +66,7 @@ | ||
| 61 | 66 | asm volatile("b _alloc_memory_main"); |
| 62 | 67 | } |
| 63 | 68 | void* _alloc_memory_main(int size, int var_num){ |
| 64 | - int i,j,candidate,after_this; | |
| 69 | + int i,j,candidate; | |
| 65 | 70 | // Assign temp var number |
| 66 | 71 | if (var_num<0) { |
| 67 | 72 | // Use ALLOC_VAR_NUM here but not ALLOC_BLOCK_NUM |
| @@ -76,6 +81,9 @@ | ||
| 76 | 81 | return 0; |
| 77 | 82 | } |
| 78 | 83 | } |
| 84 | + // Clear var to be assigned. | |
| 85 | + g_var_size[var_num]=0; | |
| 86 | + g_var_pointer[var_num]=0; | |
| 79 | 87 | while(1){ |
| 80 | 88 | // Try the block after last block |
| 81 | 89 | candidate=0; |
| @@ -87,26 +95,24 @@ | ||
| 87 | 95 | } |
| 88 | 96 | if (candidate+size<=g_max_mem) break; |
| 89 | 97 | // Check between blocks |
| 90 | - candidate=-1; | |
| 98 | + // Note that there is at least one block with zero pointer and zero size (see above). | |
| 91 | 99 | 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. | |
| 93 | 103 | 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; | |
| 97 | 110 | } |
| 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; | |
| 110 | 116 | } |
| 111 | 117 | } |
| 112 | 118 | if (0<=candidate) break; |
| @@ -132,4 +138,38 @@ | ||
| 132 | 138 | break; |
| 133 | 139 | } |
| 134 | 140 | } |
| 141 | +} | |
| 142 | + | |
| 143 | +void move_to_perm_block(int var_num){ | |
| 144 | + int i; | |
| 145 | + // Find available permanent block | |
| 146 | + for (i=ALLOC_PERM_BLOCK;i<ALLOC_BLOCK_NUM;i++){ | |
| 147 | + if (g_var_size[i]==0) break; | |
| 148 | + } | |
| 149 | + if (ALLOC_BLOCK_NUM<=i) err_no_block(); // Not found | |
| 150 | + // Available block found. | |
| 151 | + // Copy value from variable. | |
| 152 | + g_var_size[i]=g_var_size[var_num]; | |
| 153 | + g_var_pointer[i]=g_var_pointer[var_num]; | |
| 154 | + g_var_mem[i]=g_var_mem[var_num]; | |
| 155 | + // Clear variable | |
| 156 | + g_var_size[var_num]=0; | |
| 157 | + g_var_mem[var_num]=0; | |
| 158 | +} | |
| 159 | + | |
| 160 | +void move_from_perm_block(int var_num){ | |
| 161 | + int i,pointer; | |
| 162 | + pointer=(int)g_var_mem[var_num]-(int)g_heap_mem; | |
| 163 | + pointer>>=2; | |
| 164 | + // Find stored block | |
| 165 | + for (i=ALLOC_PERM_BLOCK;i<ALLOC_BLOCK_NUM;i++){ | |
| 166 | + if (0<g_var_size[i] && g_var_pointer[i]==pointer) break; | |
| 167 | + } | |
| 168 | + if (ALLOC_BLOCK_NUM<=i) err_unknown(); // Not found | |
| 169 | + // Stored block found. | |
| 170 | + // Replace pointer | |
| 171 | + g_var_size[var_num]=g_var_size[i]; | |
| 172 | + g_var_pointer[var_num]=g_var_pointer[i]; | |
| 173 | + // Clear block | |
| 174 | + g_var_size[i]=0; | |
| 135 | 175 | } |
| \ No newline at end of file |
| @@ -6,7 +6,7 @@ | ||
| 6 | 6 | // キー入力、カーソル表示関連機能 by K.Tanaka |
| 7 | 7 | // PS/2キーボード入力システム、カラーテキスト出力システム利用 |
| 8 | 8 | |
| 9 | -#include "colortext32.h" | |
| 9 | +#include "videoout.h" | |
| 10 | 10 | #include "ps2keyboard.h" |
| 11 | 11 | #include "keyinput.h" |
| 12 | 12 |
| @@ -80,6 +80,11 @@ | ||
| 80 | 80 | int len; |
| 81 | 81 | for(len=0;str[len];len++); |
| 82 | 82 | 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 | + } | |
| 83 | 88 | // String matches in the current position in source. |
| 84 | 89 | g_srcpos+=len; |
| 85 | 90 | return len; |
| @@ -97,7 +102,14 @@ | ||
| 97 | 102 | // Check if line number exists |
| 98 | 103 | next_position(); |
| 99 | 104 | 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 | |
| 101 | 113 | err=get_label(); |
| 102 | 114 | if (err) return err; |
| 103 | 115 | g_line=g_label; |
| @@ -29,6 +29,10 @@ | ||
| 29 | 29 | #define size_t unsigned int |
| 30 | 30 | #endif |
| 31 | 31 | |
| 32 | -#include "colortext32.h" | |
| 32 | +// Used for asm("wait") | |
| 33 | +#define WAIT "wait" | |
| 34 | + | |
| 35 | +#include "videoout.h" | |
| 33 | 36 | #include "SDFSIO.h" |
| 34 | 37 | #include "ps2keyboard.h" |
| 38 | +#include "debug.h" |
| @@ -9,14 +9,28 @@ | ||
| 9 | 9 | // Number of variables (including temporary ones) |
| 10 | 10 | #define ALLOC_VAR_NUM 36 |
| 11 | 11 | // 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 | |
| 13 | 13 | // Block # dedicated for PCG |
| 14 | 14 | #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 | |
| 15 | 19 | |
| 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) | |
| 16 | 24 | // RAM size used for object and heap |
| 17 | -#define RAMSIZE (1024*25) | |
| 25 | +#define RAMSIZE (PERSISTENT_RAM_SIZE-EXCEPTION_DATA_SIZE) | |
| 18 | 26 | |
| 19 | 27 | /* Enums */ |
| 28 | +enum variable{ | |
| 29 | + VAR_INTEGER, | |
| 30 | + VAR_FLOAT, | |
| 31 | + VAR_STRING | |
| 32 | +}; | |
| 33 | + | |
| 20 | 34 | enum operator{ |
| 21 | 35 | OP_VOID=0, |
| 22 | 36 | OP_OR =1, |
| @@ -28,11 +42,13 @@ | ||
| 28 | 42 | OP_LTE =7, |
| 29 | 43 | OP_MT =8, |
| 30 | 44 | 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 | |
| 36 | 52 | }; |
| 37 | 53 | enum libs{ |
| 38 | 54 | LIB_SOUND, |
| @@ -41,12 +57,16 @@ | ||
| 41 | 57 | LIB_SETDRAWCOUNT, |
| 42 | 58 | LIB_DRAWCOUNT, |
| 43 | 59 | LIB_PALETTE, |
| 60 | + LIB_GPALETTE, | |
| 44 | 61 | LIB_BGCOLOR, |
| 45 | 62 | LIB_CURSOR, |
| 46 | 63 | LIB_CLS, |
| 64 | + LIB_GCLS, | |
| 47 | 65 | LIB_COLOR, |
| 66 | + LIB_GCOLOR, | |
| 48 | 67 | LIB_KEYS, |
| 49 | 68 | LIB_RESTORE, |
| 69 | + LIB_RESTORE2, | |
| 50 | 70 | LIB_READ, |
| 51 | 71 | LIB_MIDSTR, |
| 52 | 72 | LIB_CLEAR, |
| @@ -69,13 +89,60 @@ | ||
| 69 | 89 | LIB_PCG, |
| 70 | 90 | LIB_SCROLL, |
| 71 | 91 | 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 | |
| 72 | 102 | }; |
| 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 | +}; | |
| 73 | 137 | |
| 74 | -/* Global vars */ | |
| 138 | +/* Global vars (see globalvers.c) */ | |
| 139 | +extern int g_intconst; | |
| 140 | +extern char g_valueisconst; | |
| 75 | 141 | extern int g_rnd_seed; |
| 76 | 142 | extern unsigned int g_label; |
| 77 | 143 | extern int g_sdepth; |
| 78 | 144 | extern int g_maxsdepth; |
| 145 | +extern enum variable g_lastvar; | |
| 79 | 146 | extern char* g_source; |
| 80 | 147 | extern int g_srcpos; |
| 81 | 148 | extern int g_line; |
| @@ -88,14 +155,19 @@ | ||
| 88 | 155 | extern enum operator g_last_op; |
| 89 | 156 | extern int g_end_addr; |
| 90 | 157 | extern int g_gp; |
| 158 | +extern int g_s6; | |
| 91 | 159 | extern char RAM[RAMSIZE]; |
| 160 | +extern unsigned int g_ex_data[EXCEPTION_DATA_SIZE/4]; | |
| 92 | 161 | extern int g_var_mem[ALLOC_BLOCK_NUM]; |
| 93 | 162 | extern unsigned short g_var_pointer[ALLOC_BLOCK_NUM]; |
| 94 | 163 | extern unsigned short g_var_size[ALLOC_BLOCK_NUM]; |
| 164 | +extern char g_temp_area_used; | |
| 95 | 165 | extern int* g_heap_mem; |
| 96 | 166 | extern int g_max_mem; |
| 97 | 167 | extern char g_disable_break; |
| 98 | 168 | extern unsigned char* g_pcg_font; |
| 169 | +extern char g_use_graphic; | |
| 170 | +extern unsigned short* g_graphic_area; | |
| 99 | 171 | |
| 100 | 172 | /* Prototypes */ |
| 101 | 173 | int get_gp(void); |
| @@ -105,6 +177,11 @@ | ||
| 105 | 177 | char* compile_line(void); |
| 106 | 178 | int nextCodeIs(char* str); |
| 107 | 179 | |
| 180 | +char* init_file(char* buff,char* appname); | |
| 181 | +void close_file(); | |
| 182 | +void read_file(int blocklen); | |
| 183 | +char* compile_file(); | |
| 184 | + | |
| 108 | 185 | void err_break(void); |
| 109 | 186 | void err_music(char* str); |
| 110 | 187 | void err_data_not_found(void); |
| @@ -114,6 +191,7 @@ | ||
| 114 | 191 | void err_div_zero(void); |
| 115 | 192 | void err_unkonwn(void); |
| 116 | 193 | void err_unexp_next(void); |
| 194 | +void err_no_block(void); | |
| 117 | 195 | char* resolve_label(int s6); |
| 118 | 196 | |
| 119 | 197 | void set_sound(unsigned long* data); |
| @@ -123,15 +201,20 @@ | ||
| 123 | 201 | |
| 124 | 202 | char* statement(void); |
| 125 | 203 | char* gosub_statement(); |
| 204 | +char* graphic_statement(enum functions func); | |
| 126 | 205 | |
| 127 | 206 | char* function(void); |
| 128 | 207 | char* str_function(void); |
| 208 | +char* float_function(void); | |
| 129 | 209 | |
| 130 | 210 | void call_library(void); |
| 211 | +void reset_dataread(); | |
| 131 | 212 | |
| 132 | 213 | void free_temp_str(char* str); |
| 133 | 214 | void* alloc_memory(int size, int var_num); |
| 134 | 215 | 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); | |
| 135 | 218 | |
| 136 | 219 | char* link(void); |
| 137 | 220 | char* get_label(void); |
| @@ -138,13 +221,24 @@ | ||
| 138 | 221 | void* search_label(unsigned int label); |
| 139 | 222 | |
| 140 | 223 | char* get_string(); |
| 224 | +char* simple_string(void); | |
| 141 | 225 | |
| 142 | 226 | char* get_operator(void); |
| 227 | +char* get_floatOperator(void); | |
| 143 | 228 | char* calculation(enum operator op); |
| 229 | +char* calculation_float(enum operator op); | |
| 230 | +int lib_float(int ia0,int iv0, enum operator a1); | |
| 144 | 231 | |
| 232 | +char* get_dim_value(char b1); | |
| 145 | 233 | char* get_simple_value(void); |
| 146 | 234 | char* get_value(); |
| 235 | +char* get_floatOrValue(); | |
| 236 | +char* get_stringFloatOrValue(); | |
| 147 | 237 | |
| 238 | +void blue_screen(void); | |
| 239 | + | |
| 240 | +char* get_float(); | |
| 241 | + | |
| 148 | 242 | /* Error messages */ |
| 149 | 243 | #define ERR_SYNTAX (char*)(g_err_str[0]) |
| 150 | 244 | #define ERR_NE_BINARY (char*)(g_err_str[1]) |
| @@ -160,6 +254,10 @@ | ||
| 160 | 254 | #define ERR_MULTIPLE_LABEL (char*)(g_err_str[11]) |
| 161 | 255 | #define ERR_BREAK (char*)(g_err_str[12]) |
| 162 | 256 | #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]) | |
| 163 | 261 | |
| 164 | 262 | /* Macros */ |
| 165 | 263 |
| @@ -167,27 +265,39 @@ | ||
| 167 | 265 | #define next_position() while(g_source[g_srcpos]==' ') {g_srcpos++;} |
| 168 | 266 | |
| 169 | 267 | // 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 | |
| 171 | 269 | |
| 172 | 270 | // Returns priority of operator |
| 173 | -#define priority(x) (int)g_priority[(int)x] | |
| 271 | +#define priority(x) (int)g_priority[(int)(x)] | |
| 174 | 272 | |
| 175 | 273 | // 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 | |
| 178 | 276 | #define call_lib_code(x) \ |
| 179 | 277 | check_obj_space(2);\ |
| 180 | 278 | g_object[g_objpos++]=0x02E0F809;\ |
| 181 | - g_object[g_objpos++]=0x24070000|(x&0x0000FFFF) | |
| 279 | + g_object[g_objpos++]=0x24070000|((x)&0x0000FFFF) | |
| 182 | 280 | |
| 183 | 281 | // Division macro for unsigned long |
| 184 | 282 | // 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)) | |
| 186 | 284 | |
| 187 | 285 | // Divide by 10 (valid for 32 bits) |
| 188 | 286 | #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)) | |
| 190 | 288 | |
| 191 | 289 | // Divide by 36 (valid for 32 bits) |
| 192 | 290 | #define div36_32(x) div32(x,0xe38e38e4,37) |
| 193 | 291 | #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 | + } |
| @@ -1,8 +1,8 @@ | ||
| 1 | 1 | /* |
| 2 | 2 | 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 | |
| 4 | 5 | http://hp.vector.co.jp/authors/VA016157/ |
| 5 | - kmorimatsu@users.sourceforge.jp | |
| 6 | 6 | */ |
| 7 | 7 | |
| 8 | 8 | #include <xc.h> |
| @@ -9,14 +9,15 @@ | ||
| 9 | 9 | #include "api.h" |
| 10 | 10 | #include "compiler.h" |
| 11 | 11 | |
| 12 | -FSFILE* g_fhandle; | |
| 13 | -char* g_fbuff; | |
| 12 | +static FSFILE* g_fhandle; | |
| 13 | +static char* g_fbuff; | |
| 14 | +static int g_size; | |
| 14 | 15 | |
| 15 | -int init_file(char* buff,char* appname){ | |
| 16 | +char* init_file(char* buff,char* appname){ | |
| 16 | 17 | // Open file |
| 17 | 18 | g_fhandle=FSfopen(appname,"r"); |
| 18 | 19 | if (!g_fhandle) { |
| 19 | - return -1; | |
| 20 | + return ERR_UNKNOWN; | |
| 20 | 21 | } |
| 21 | 22 | g_fbuff=buff; |
| 22 | 23 | g_line=0; |
| @@ -24,45 +25,70 @@ | ||
| 24 | 25 | return 0; |
| 25 | 26 | } |
| 26 | 27 | |
| 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 | +} | |
| 33 | 31 | |
| 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 { | |
| 46 | 44 | // Shift buffer and source position 256 bytes. |
| 47 | 45 | for(i=0;i<256;i++) g_fbuff[i]=g_fbuff[i+256]; |
| 48 | 46 | 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]=' '; | |
| 55 | 65 | } |
| 66 | + if (g_fbuff[i]==0x0a || g_fbuff[i]==0x0d) in_string=escape=0; | |
| 56 | 67 | } |
| 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; | |
| 59 | 85 | // Compile last few lines. |
| 60 | - while(g_srcpos<size-1){ | |
| 86 | + while(g_srcpos<g_size-1){ | |
| 61 | 87 | err=compile_line(); |
| 62 | 88 | if (err) return err; |
| 63 | 89 | } |
| 64 | - // Add "END" statement. | |
| 65 | - g_source="END\n"; | |
| 90 | + // Add "DATA 0" and "END" statements. | |
| 91 | + g_source="DATA 0:END\n"; | |
| 66 | 92 | g_srcpos=0; |
| 67 | 93 | err=compile_line(); |
| 68 | 94 | if (err) return err; |
| @@ -1,12 +1,13 @@ | ||
| 1 | 1 | /* |
| 2 | 2 | This file is provided under the LGPL license ver 2.1. |
| 3 | - Written by K.Tanaka | |
| 3 | + Written by K.Tanaka & Katsumi | |
| 4 | 4 | http://www.ze.em-net.ne.jp/~kenken/index.html |
| 5 | + http://hp.vector.co.jp/authors/VA016157/ | |
| 5 | 6 | */ |
| 6 | 7 | |
| 7 | 8 | // 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 | |
| 10 | 11 | |
| 11 | 12 | // 利用システム |
| 12 | 13 | // ps2keyboard.X.a : PS/2キーボード入力システムライブラリ |
| @@ -13,15 +14,12 @@ | ||
| 13 | 14 | // lib_colortext32.a : カラービデオ信号出力システムライブラリ(30×27テキスト版) |
| 14 | 15 | // libsdfsio.a : SDカードアクセス用ライブラリ |
| 15 | 16 | |
| 16 | -#define SYSVER1 "Nauplia" | |
| 17 | -#define SYSVER2 "1.01" | |
| 18 | -#define BASVER "KM-1120" | |
| 19 | - | |
| 20 | 17 | #include <xc.h> |
| 21 | 18 | #include "api.h" |
| 22 | 19 | #include "compiler.h" |
| 23 | 20 | #include "editor.h" |
| 24 | 21 | #include "keyinput.h" |
| 22 | +#include "main.h" | |
| 25 | 23 | |
| 26 | 24 | //外付けクリスタル with PLL (16倍) |
| 27 | 25 | #pragma config PMDL1WAY = OFF, IOL1WAY = OFF |
| @@ -28,13 +26,12 @@ | ||
| 28 | 26 | #pragma config FPLLIDIV = DIV_1, FPLLMUL = MUL_16, FPLLODIV = DIV_1 |
| 29 | 27 | #pragma config FNOSC = PRIPLL, FSOSCEN = OFF, POSCMOD = XT, OSCIOFNC = OFF |
| 30 | 28 | #pragma config FPBDIV = DIV_1, FWDTEN = OFF, JTAGEN = OFF, ICESEL = ICS_PGx1 |
| 29 | +#pragma config FCKSM = CSECMD | |
| 31 | 30 | |
| 32 | 31 | #define mBMXSetRAMKernProgOffset(offset) (BMXDKPBA = (offset)) |
| 33 | 32 | #define mBMXSetRAMUserDataOffset(offset) (BMXDUDBA = (offset)) |
| 34 | 33 | #define mBMXSetRAMUserProgOffset(offset) (BMXDUPBA = (offset)) |
| 35 | 34 | |
| 36 | -#define FILENAME_FLASH_ADDRESS 0x9D005800 | |
| 37 | - | |
| 38 | 35 | // INIファイル指定キーワード(8文字以内) |
| 39 | 36 | const char InitKeywords[][9]={ |
| 40 | 37 | "106KEY","101KEY","NUMLOCK","CAPSLOCK","SCRLLOCK" |
| @@ -122,9 +119,31 @@ | ||
| 122 | 119 | } |
| 123 | 120 | FSfclose(fp); |
| 124 | 121 | } |
| 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 | + | |
| 125 | 138 | int main(void){ |
| 126 | 139 | char *appname,*s; |
| 127 | 140 | |
| 141 | + if(DEVCFG1 & 0x8000){ | |
| 142 | + // Set Clock switching enabled and reset | |
| 143 | + NVMWriteWord(&DEVCFG1,DEVCFG1 & 0xffff7fff); | |
| 144 | + SoftReset(); | |
| 145 | + } | |
| 146 | + | |
| 128 | 147 | /* ポートの初期設定 */ |
| 129 | 148 | TRISA = 0x0000; // PORTA全て出力 |
| 130 | 149 | ANSELA = 0x0000; // 全てデジタル |
| @@ -138,14 +157,17 @@ | ||
| 138 | 157 | RPB5R=4; //RPB5:SDO2 |
| 139 | 158 | |
| 140 | 159 | // 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); | |
| 144 | 163 | |
| 145 | 164 | ps2mode(); //RA1オン(PS/2有効化マクロ) |
| 146 | 165 | init_composite(); // ビデオメモリクリア、割り込み初期化、カラービデオ出力開始 |
| 147 | 166 | setcursor(0,0,COLOR_NORMALTEXT); |
| 148 | 167 | |
| 168 | + // Show blue screen if exception before soft reset. | |
| 169 | + blue_screen(); | |
| 170 | + | |
| 149 | 171 | printstr("MachiKania BASIC System\n"); |
| 150 | 172 | printstr(" Ver "SYSVER1" "SYSVER2" by KENKEN\n"); |
| 151 | 173 | printstr("BASIC Compiler "BASVER"\n"); |
| @@ -154,7 +176,7 @@ | ||
| 154 | 176 | setcursorcolor(COLOR_NORMALTEXT); |
| 155 | 177 | printstr("Init File System..."); |
| 156 | 178 | // Initialize the File System |
| 157 | - if(FSInit()==NULL){ //ファイルシステム初期化 | |
| 179 | + if(FSInit()==FALSE){ //ファイルシステム初期化 | |
| 158 | 180 | //エラーの場合停止 |
| 159 | 181 | setcursorcolor(COLOR_ERRORTEXT); |
| 160 | 182 | printstr("\nFile System Error\n"); |
| @@ -190,5 +212,5 @@ | ||
| 190 | 212 | // buttonmode(); //ボタン有効化 |
| 191 | 213 | g_disable_break=1; // Breakキー無効化 |
| 192 | 214 | runbasic(tempfile,0); |
| 193 | - while(1) asm("wait"); | |
| 215 | + while(1) asm(WAIT); | |
| 194 | 216 | } |
| @@ -60,8 +60,8 @@ | ||
| 60 | 60 | g_srcpos++; |
| 61 | 61 | b1=g_source[g_srcpos]; |
| 62 | 62 | } 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) { | |
| 65 | 65 | g_srcpos=prevpos; |
| 66 | 66 | return ERR_LABEL_LONG; |
| 67 | 67 | } |
| @@ -122,20 +122,114 @@ | ||
| 122 | 122 | } |
| 123 | 123 | } |
| 124 | 124 | |
| 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 | + | |
| 125 | 190 | /* |
| 126 | 191 | Following codes are dedicated to specific use: |
| 127 | 192 | 0x0810xxxx, 0x0811xxxx: GOTO statement |
| 128 | 193 | 0x0812xxxx, 0x0813xxxx: GOSUB statement |
| 129 | 194 | 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. | |
| 130 | 213 | */ |
| 131 | 214 | |
| 132 | 215 | char* link(void){ |
| 133 | 216 | int pos; |
| 134 | 217 | unsigned int code1,code2,label; |
| 218 | + g_fileline=0; | |
| 135 | 219 | for(pos=0;pos<g_objpos;pos++){ |
| 136 | 220 | 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: | |
| 139 | 233 | // GOTO |
| 140 | 234 | code2=g_object[pos+1]; |
| 141 | 235 | if ((code2&0xFFFF0000)!=0x08110000) continue; |
| @@ -151,7 +245,7 @@ | ||
| 151 | 245 | g_object[pos++]=code1; |
| 152 | 246 | g_object[pos]=0x00000000; // nop |
| 153 | 247 | break; |
| 154 | - case 0x08120000: | |
| 248 | + case 0x0812: | |
| 155 | 249 | // GOSUB |
| 156 | 250 | code2=g_object[pos+1]; |
| 157 | 251 | if ((code2&0xFFFF0000)!=0x08130000) continue; |
| @@ -167,19 +261,105 @@ | ||
| 167 | 261 | g_object[pos++]=0x00000000; // nop |
| 168 | 262 | g_object[pos]=code2; |
| 169 | 263 | break; |
| 170 | - case 0x08140000: | |
| 264 | + case 0x0814: | |
| 171 | 265 | // SOUND etc, for setting v0 as pointer to label/line |
| 172 | 266 | code2=g_object[pos+1]; |
| 173 | 267 | if ((code2&0xFFFF0000)!=0x08150000) continue; |
| 174 | 268 | code1&=0x0000FFFF; |
| 175 | 269 | code2&=0x0000FFFF; |
| 176 | - g_label=label; | |
| 177 | 270 | label=(code1<<16)|code2; |
| 178 | 271 | code1=(int)search_label(label); |
| 272 | + g_label=label; | |
| 179 | 273 | if (!code1) return ERR_LABEL_NF; |
| 180 | 274 | g_object[pos++]=0x3C020000|((code1>>16)&0x0000FFFF); // lui v0,xxxx |
| 181 | 275 | g_object[pos] =0x34420000|(code1&0x0000FFFF); // ori v0,v0,xxxx |
| 182 | 276 | 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; | |
| 183 | 363 | default: |
| 184 | 364 | break; |
| 185 | 365 | } |
| @@ -17,8 +17,9 @@ | ||
| 17 | 17 | 「CHR$($22)」のように記述することが出来ます。 |
| 18 | 18 | |
| 19 | 19 | <命令> |
| 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 | +指します。[ ]は省略可能である事を示します。 | |
| 22 | 23 | |
| 23 | 24 | 命令同士を「:」で区切ることにより、一行で複数のコマンドを処理すること |
| 24 | 25 | が出来ます。 |
| @@ -25,6 +26,10 @@ | ||
| 25 | 26 | |
| 26 | 27 | BGCOLOR r,g,b |
| 27 | 28 | 背景色指定。 |
| 29 | +BREAK | |
| 30 | + FOR-NEXT, DO-LOOP, WHILE-WENDループから抜け出す。 | |
| 31 | +CDATA x[,y[,z[...]]] | |
| 32 | + データー列を8ビット整数値で指定する。 | |
| 28 | 33 | CLEAR |
| 29 | 34 | すべての文字列型変数と整数型配列を破棄し、整数値を0とする。また、 |
| 30 | 35 | PCGの使用をやめ、表示キャラクターをリセットする。 |
| @@ -34,12 +39,27 @@ | ||
| 34 | 39 | テキスト色指定。 |
| 35 | 40 | CURSOR x,y |
| 36 | 41 | カーソル位置指定。 |
| 37 | -DATA x[,y[,z[...]]] | |
| 38 | - データー列を整数値で指定する。 | |
| 42 | +CDATA xxx[,yyy[,zzz[...]]] | |
| 43 | + データー列を8ビット整数値で指定する。 | |
| 44 | +DATA xxx[,yyy[,zzz[...]]] | |
| 45 | + データー列を整数値もしくは文字列で指定する。 | |
| 39 | 46 | DIM xxx [, yyy [, zzz [, ... ]]] |
| 40 | - 整数型の一次元配列を割り当てる。 | |
| 47 | + 整数型もしくは浮動小数点型の配列を割り当てる。 | |
| 41 | 48 | 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の場合、繰り返す。 | |
| 43 | 63 | DRAWCOUNT |
| 44 | 64 | DRAWCOUNT値を指定する。DRAWCOUNT値に付いては、DRAWCOUNT()関数を |
| 45 | 65 | 参照。 |
| @@ -53,21 +73,41 @@ | ||
| 53 | 73 | までのステートメントを、繰り返し実行する。繰り返しのたび、xの値は |
| 54 | 74 | wwwずつ増加する(省略された場合は1ずつ)。「NEXT」の次に何も記述 |
| 55 | 75 | しないことに注意。 |
| 56 | -GOSUB xxx | |
| 57 | - 現在の実行位置を記憶し、xxx行目(もしくはラベル)に移動する。 | |
| 76 | +GOSUB xxx [, yyy [, zzz [, ... ]]] | |
| 77 | + 現在の実行位置を記憶し、xxx行目(もしくはラベル)に移動する。yyy, zzz | |
| 78 | + 等は、サブルーチンに引き継がれる引数(ARGS()関数を参照)。 | |
| 58 | 79 | GOTO xxx |
| 59 | 80 | 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ステートメントの次には何も記入しないことに注意。 | |
| 62 | 94 | LABEL xxx |
| 63 | 95 | GOTO/GOSUBのジャンプ先を登録する。xxxは、英数字6文字以内の文字列。 |
| 64 | 96 | [LET] x=yyy |
| 65 | - yで示された計算結果を、xに代入する。「LET」は省略可。 | |
| 97 | + yで示された計算結果を、x(整数型変数)に代入する。「LET」は省略可。 | |
| 98 | +[LET] x#=yyy | |
| 99 | + yで示された計算結果を、x(不動州数点方型変数)に代入する。「LET」は省略可。 | |
| 66 | 100 | [LET] x$=yyy |
| 67 | 101 | yyyで示された文字列(もしくは連結結果;連結演算子は「+」)を、x$に |
| 68 | 102 | 代入する。「LET」は省略可。 |
| 69 | 103 | MUSIC x$ |
| 70 | 104 | BGMを演奏する。詳細は、下記<MUSIC>の項を参照。 |
| 105 | +VAR xxx [, yyy [, zzz [, ... ]]] | |
| 106 | + サブルーチン内で使う、ローカル変数を指定する。xxx, yyy等は、A-Zの | |
| 107 | + アルファベットで指定する。 | |
| 108 | +WHILE x | |
| 109 | +WEND | |
| 110 | + x が0以外の場合、WHILE文からWEND文までのステートメントを繰り返し実行する。 | |
| 71 | 111 | PALETTE n,r,g,b |
| 72 | 112 | パレット指定。 |
| 73 | 113 | PCG x,y,z |
| @@ -75,7 +115,7 @@ | ||
| 75 | 115 | ターデーター。詳細は、下記<PCG>の項を参照。 |
| 76 | 116 | POKE x,y |
| 77 | 117 | xで示される物理的アドレスに、yで示される値(1バイト値)を書き込む。 |
| 78 | -PRINT [ xまたはx$ [ ,または; [ yまたはy$ [ ... ]]]] | |
| 118 | +PRINT [ xまたはx$またはx# [ ,または; [ yまたはy$またはy# [ ... ]]]] | |
| 79 | 119 | ディスプレイに、整数値または文字列を表示する。「;」を使用した場 |
| 80 | 120 | 合、次の表示が続けて行われる。「,」を使用した場合、10文字ずつ |
| 81 | 121 | に区切って表示される。どちらも使用しない場合、次の表示は行を変え |
| @@ -93,6 +133,14 @@ | ||
| 93 | 133 | SOUND xxx |
| 94 | 134 | 効果音を再生する。詳細は、下記<SOUND>の項を参照。xxxは行番号もしく |
| 95 | 135 | はラベル。 |
| 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と同じ。 | |
| 96 | 144 | USEPCG [x] |
| 97 | 145 | PCGを使用、もしくは使用停止する。x=0で使用停止、x=1で使用、x=2で |
| 98 | 146 | キャラクターをリセットして使用。xを省略した場合は、x=1と同じ。 |
| @@ -101,24 +149,62 @@ | ||
| 101 | 149 | xで示された時間、プログラムの実行を停止する。xが60の場合、約1秒間 |
| 102 | 150 | 停止。 |
| 103 | 151 | |
| 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 | +<整数型関数> | |
| 105 | 181 | 以下、x, y, zは整数値を、x$, y$, z$は文字列を指します。[ ]は省略可能である事 |
| 106 | 182 | を示します。 |
| 107 | 183 | |
| 108 | 184 | ABS(x) |
| 109 | 185 | xの絶対値を返す。 |
| 186 | +ARGS(x) | |
| 187 | + サブルーチン中で、GOSUBに渡されたx番目の引数を整数値として取り出す。 | |
| 110 | 188 | ASC(x$) |
| 111 | 189 | 文字列の最初の一文字の、アスキーコードを返す。 |
| 190 | +CREAD() | |
| 191 | + DATA文の後から、一つずつデーター(8ビット整数値)を読み出す。「READ()」 | |
| 192 | + 関数も参照。 | |
| 112 | 193 | DRAWCOUNT() |
| 113 | 194 | DRAWCOUNT値を得る。DRAWCOUNTは16ビット整数値で、1/60秒ごとに1ずつ |
| 114 | 195 | 増える。 |
| 115 | -GOSUB(xxx) | |
| 196 | +GCOLOR(x,y) | |
| 197 | + グラフィック座標(x,y)の表示中パレット番号を返す。 | |
| 198 | +GOSUB(xxx [, y [, z [, ... ]]]) | |
| 116 | 199 | GOSUB命令と同じだが、戻り値(RETURNを参照)を得ることが出来る。xxxは、 |
| 117 | - ラベルもしくは行番号。 | |
| 200 | + ラベルもしくは行番号。。yyy, zzz 等は、サブルーチンに引き継がれる引数( | |
| 201 | + ARGS()関数を参照)。 | |
| 118 | 202 | INKEY([x]) |
| 119 | 203 | xを指定しない場合、現在押されているキーのASCII値を返す。押されていな |
| 120 | 204 | い場合は、0。ASCII値でxを指定した場合、そのキーが押されているかどう |
| 121 | 205 | かを返す。 |
| 206 | +INT(x#) | |
| 207 | + 実数値x#を整数値に変換して返す。 | |
| 122 | 208 | KEYS([x]) |
| 123 | 209 | キー入力を得る。xの値は以下の通り。xを指定しない場合は、x=63と同じ。 |
| 124 | 210 | KEYUP: 1 |
| @@ -136,7 +222,8 @@ | ||
| 136 | 222 | PEEK(x) |
| 137 | 223 | xで示される物理アドレスから1バイト読み取り、返す。 |
| 138 | 224 | READ() |
| 139 | - DATA文の後から、一つずつデーター(整数値)を読み出す。 | |
| 225 | + DATA文の後から、一つずつデーター(32ビット整数値)を読み出す。「CREAD()」 | |
| 226 | + 関数も参照。 | |
| 140 | 227 | RND() |
| 141 | 228 | 0から32767までの擬似乱数を返す。 |
| 142 | 229 | SGN(x) |
| @@ -143,27 +230,97 @@ | ||
| 143 | 230 | xの符号(-1, 0, または1)を返す。 |
| 144 | 231 | STRNCMP(x$,y$,z) |
| 145 | 232 | 2つの文字列のうちz文字分を比較し、結果を返す。同じ文字列の場合は0。 |
| 233 | +SYSTEM(x) | |
| 234 | + 様々なシステム値を、整数値で返す。「<システム変数>」の項を参照。 | |
| 146 | 235 | TVRAM([x]) |
| 147 | 236 | ビデオRAMのx番目の内容を、バイト値で返す。xを省略した場合、ビデオ |
| 148 | 237 | RAMの開始位置の物理アドレスを返す。 |
| 149 | 238 | VAL(x$) |
| 150 | 239 | 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 | +<文字列型関数> | |
| 151 | 294 | A$(x [,y])など |
| 152 | 295 | xの値が0の場合、文字列全体を返す。 |
| 153 | 296 | xの値が正の場合、xで示される位置より右側の文字列を返す。 |
| 154 | 297 | xの値が負のとき、文字列の右側x文字を返す。 |
| 155 | 298 | yが指定された場合、y文字分の文字列を返す。 |
| 299 | +ARGS$(x) | |
| 300 | + サブルーチン中で、GOSUBに渡されたx番目の引数を文字列として取り出す。 | |
| 156 | 301 | CHR$(x) |
| 157 | 302 | xをアスキーコードとする文字を返す。 |
| 158 | 303 | DEC$(x) |
| 159 | 304 | xの値を、10進数の文字列として返す。 |
| 305 | +FLOAT$(x#) | |
| 306 | + 実数値x#を、10進数の文字列として返す。 | |
| 307 | +GOSUB$(xxx [, y [, z [, ... ]]]) | |
| 308 | + GOSUB命令と同じだが、戻り値(RETURNを参照)を文字列として得ることが出来る。 | |
| 309 | + xxxは、ラベルもしくは行番号。。yyy, zzz 等は、サブルーチンに引き継がれる引数 | |
| 310 | + (ARGS()関数を参照)。 | |
| 160 | 311 | HEX$(x [,y]) |
| 161 | 312 | xの値を、16進数の文字列として返す。yが指定された場合、yバイト長の |
| 162 | 313 | 文字列になる。 |
| 163 | 314 | INPUT$() |
| 164 | 315 | 文字列入力状態になり、入力が終了すると(Enterが押されると)文字列を返す。 |
| 316 | +SPRINTF$(x$,y#) | |
| 317 | + x$で示される書式に従って、実数y#の内容を文字列として返す。 | |
| 318 | +SYSTEM$(x) | |
| 319 | + 様々なシステム値を、文字列で返す。「<システム変数>」の項を参照。 | |
| 320 | +READ$() | |
| 321 | + DATA文の後から、一つずつ文字列データーを読み出す。 | |
| 165 | 322 | |
| 166 | -<演算子> | |
| 323 | +<整数演算子> | |
| 167 | 324 | -x |
| 168 | 325 | 符号を反転 |
| 169 | 326 | x + y |
| @@ -176,6 +333,10 @@ | ||
| 176 | 333 | 整数除算 |
| 177 | 334 | x % y |
| 178 | 335 | 整数剰余 |
| 336 | +x >> y | |
| 337 | + xの値をyビット右シフト | |
| 338 | +x << y | |
| 339 | + xの値をyビット左シフト | |
| 179 | 340 | x = y |
| 180 | 341 | 2つの整数値が等しい場合に1、そうでないときに0 |
| 181 | 342 | x != y |
| @@ -194,8 +355,6 @@ | ||
| 194 | 355 | xとyの値のビットごとの OR |
| 195 | 356 | x XOR y |
| 196 | 357 | xとyの値のビットごとの XOR |
| 197 | -x$ + y$ | |
| 198 | - 文字列の連結 | |
| 199 | 358 | |
| 200 | 359 | なお、整数演算子の優先順位は、優先度が高いものから以下の順です。 |
| 201 | 360 |
| @@ -202,6 +361,7 @@ | ||
| 202 | 361 | + - (単項演算子) |
| 203 | 362 | * / % |
| 204 | 363 | + - (加算・減算) |
| 364 | +<< >> | |
| 205 | 365 | < <= > >= |
| 206 | 366 | = != |
| 207 | 367 | XOR |
| @@ -208,6 +368,48 @@ | ||
| 208 | 368 | AND |
| 209 | 369 | OR |
| 210 | 370 | |
| 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 | + | |
| 211 | 413 | <MUSIC> |
| 212 | 414 | MUSIC命令では、BGM用のデーターを文字列で指定します。文字列の書式は、ABC |
| 213 | 415 | notationに準拠しています。ただし、すべての記法が使えるわけではありません。 |
| @@ -265,12 +467,66 @@ | ||
| 265 | 467 | |
| 266 | 468 | として下さい。 |
| 267 | 469 | |
| 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 | + | |
| 268 | 525 | <ヒント> |
| 269 | -FOR文では、TOステートメントの次に書かれた値に合致する場合(超えた時ではなく) | |
| 270 | -に、ループから抜ける仕様です。また、FOR-NEXTループの途中で、GOTO文でループの | |
| 526 | +FOR-NEXTループ、WHILE-WENDループ、DO-LOOPループの途中で、GOTO文でループの | |
| 271 | 527 | 外に飛んだり、RETURN文を実行したりすると、予期せぬ結果(機器のリセット等)を |
| 272 | -引き起こします。ただし、GOSUB文でサブルーチンを呼んだり、別のFOR-NEXTをネス | |
| 273 | -トして使う事は可能です。 | |
| 528 | +引き起こします。ただし、GOSUB文でサブルーチンを呼んだり、別のループをネスト | |
| 529 | +して使う事は可能です。 | |
| 274 | 530 | |
| 275 | 531 | ON GOTO分やON GOSUB文はサポートしていません。ただし、例えば次のように記述す |
| 276 | 532 | ることで、同様の動作をさせることは可能です。 |
| @@ -286,6 +542,24 @@ | ||
| 286 | 542 | てみて下さい。 |
| 287 | 543 | |
| 288 | 544 | <バージョン履歴> |
| 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 | + | |
| 289 | 563 | ・KM-1120 2016年2月公開。 |
| 290 | 564 | 1.PCG機能を追加。 |
| 291 | 565 | 2.SCROLL命令を追加。 |
| @@ -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 |
| @@ -9,6 +9,7 @@ | ||
| 9 | 9 | #include "editor.h" |
| 10 | 10 | #include "keyinput.h" |
| 11 | 11 | #include "compiler.h" |
| 12 | +#include "main.h" | |
| 12 | 13 | |
| 13 | 14 | struct _TBUF{ |
| 14 | 15 | //リンク付きのテキストバッファ |
| @@ -61,7 +62,7 @@ | ||
| 61 | 62 | void wait60thsec(unsigned short n){ |
| 62 | 63 | // 60分のn秒ウェイト(ビデオ画面の最下行信号出力終了まで待つ) |
| 63 | 64 | n+=drawcount; |
| 64 | - while(drawcount!=n) asm("wait"); | |
| 65 | + while(drawcount!=n) asm(WAIT); | |
| 65 | 66 | } |
| 66 | 67 | |
| 67 | 68 | unsigned int bpixtopos(_tbuf *bp,unsigned int ix){ |
| @@ -102,23 +103,30 @@ | ||
| 102 | 103 | // テキスト全体の先頭からline行目のテキストバッファ上の位置を返す |
| 103 | 104 | // 戻り値 テキストバッファポインタ |
| 104 | 105 | // *pix(戻り値):戻り値テキストバッファの先頭からの位置(ポインタ渡し) |
| 105 | - _tbuf *bp; | |
| 106 | - int ix; | |
| 106 | + _tbuf *bp,*bp2; | |
| 107 | + int ix,ix2; | |
| 107 | 108 | bp=TBufstart; |
| 109 | + bp2=TBufstart; | |
| 108 | 110 | ix=0; |
| 111 | + ix2=0; | |
| 109 | 112 | while(line>1){ |
| 110 | 113 | while(1){ |
| 111 | 114 | if(ix>=bp->n){ |
| 115 | + if(bp->next==NULL) break; | |
| 112 | 116 | bp=bp->next; |
| 113 | 117 | ix=0; |
| 114 | 118 | continue; |
| 115 | 119 | } |
| 116 | - if(bp->Buf[ix++] == '\n') break; | |
| 120 | + if(bp->Buf[ix++] == '\n'){ | |
| 121 | + bp2=bp; | |
| 122 | + ix2=ix; | |
| 123 | + break; | |
| 124 | + } | |
| 117 | 125 | } |
| 118 | 126 | line--; |
| 119 | 127 | } |
| 120 | - *pix=ix; | |
| 121 | - return bp; | |
| 128 | + *pix=ix2; | |
| 129 | + return bp2; | |
| 122 | 130 | } |
| 123 | 131 | |
| 124 | 132 | _tbuf * newTBuf(_tbuf *prev){ |
| @@ -1015,7 +1023,7 @@ | ||
| 1015 | 1023 | if(vk==VK_ESCAPE) return -1; |
| 1016 | 1024 | } |
| 1017 | 1025 | //ファイルシステム初期化 |
| 1018 | - if(FSInit()!=NULL) return 0; //成功 | |
| 1026 | + if(FSInit()!=FALSE) return 0; //成功 | |
| 1019 | 1027 | //エラーの場合 |
| 1020 | 1028 | setcursorcolor(COLOR_ERRORTEXT); |
| 1021 | 1029 | printstr((unsigned char *)Message2);//File System Error |
| @@ -14,14 +14,18 @@ | ||
| 14 | 14 | "Divided by zero", |
| 15 | 15 | "Not yet implemented", |
| 16 | 16 | "Label or line number not found: ", |
| 17 | - "Label too long", | |
| 17 | + "Label too long or too short", | |
| 18 | 18 | "String too complexed", |
| 19 | 19 | "Data not found", |
| 20 | 20 | "Unknown error", |
| 21 | - "Music syntax error\n", | |
| 21 | + "Music syntax error:'", | |
| 22 | 22 | " found more than twice", |
| 23 | 23 | "Break", |
| 24 | 24 | "Unexpected NEXT or RETURN statement", |
| 25 | + "Cannot assign temporary block", | |
| 26 | + "GOSUB fuction cannot be used after string-handling", | |
| 27 | + "Invalid BREAK statement in line ", | |
| 28 | + "Invalid ELSE/IF statement in line ", | |
| 25 | 29 | }; |
| 26 | 30 | |
| 27 | 31 | char* resolve_label(int s6){ |
| @@ -61,7 +65,7 @@ | ||
| 61 | 65 | void pre_end_addr(int s6){ |
| 62 | 66 | int i,j; |
| 63 | 67 | char str[7]; |
| 64 | - if (s6<0) s6=0-s6; | |
| 68 | + if (s6<0) s6=s6&0x7fffffff; | |
| 65 | 69 | g_label=s6; |
| 66 | 70 | if (s6<65536) { |
| 67 | 71 | // Line number |
| @@ -121,6 +125,10 @@ | ||
| 121 | 125 | void err_music(char* str){ |
| 122 | 126 | printstr(ERR_MUSIC); |
| 123 | 127 | 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)"); | |
| 124 | 132 | end_exec(); |
| 125 | 133 | } |
| 126 | 134 |
| @@ -128,3 +136,8 @@ | ||
| 128 | 136 | printstr(ERR_UNEXP_NEXT); |
| 129 | 137 | end_exec(); |
| 130 | 138 | } |
| 139 | + | |
| 140 | +void err_no_block(void){ | |
| 141 | + printstr(ERR_NO_BLOCK); | |
| 142 | + end_exec(); | |
| 143 | +} |
| @@ -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); |
| @@ -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 |
| @@ -12,6 +12,7 @@ | ||
| 12 | 12 | () |
| 13 | 13 | * / % |
| 14 | 14 | + - |
| 15 | +<< >> | |
| 15 | 16 | < <= > >= |
| 16 | 17 | = != |
| 17 | 18 | XOR |
| @@ -27,8 +28,9 @@ | ||
| 27 | 28 | 3, // OP_XOR |
| 28 | 29 | 4,4, // OP_EQ, OP_NEQ |
| 29 | 30 | 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 | |
| 32 | 34 | }; |
| 33 | 35 | |
| 34 | 36 | enum operator g_last_op; |
| @@ -46,8 +48,11 @@ | ||
| 46 | 48 | case '-': g_last_op=OP_SUB; break; |
| 47 | 49 | case '+': g_last_op=OP_ADD; break; |
| 48 | 50 | case '>': |
| 49 | - if (b2=='=') { | |
| 51 | + if (b2=='>') { | |
| 50 | 52 | g_srcpos++; |
| 53 | + g_last_op=OP_SHR; | |
| 54 | + } else if (b2=='=') { | |
| 55 | + g_srcpos++; | |
| 51 | 56 | g_last_op=OP_MTE; |
| 52 | 57 | } else { |
| 53 | 58 | g_last_op=OP_MT; |
| @@ -54,8 +59,11 @@ | ||
| 54 | 59 | } |
| 55 | 60 | break; |
| 56 | 61 | case '<': |
| 57 | - if (b2=='=') { | |
| 62 | + if (b2=='<') { | |
| 58 | 63 | g_srcpos++; |
| 64 | + g_last_op=OP_SHL; | |
| 65 | + } else if (b2=='=') { | |
| 66 | + g_srcpos++; | |
| 59 | 67 | g_last_op=OP_LTE; |
| 60 | 68 | } else { |
| 61 | 69 | g_last_op=OP_LT; |
| @@ -96,8 +104,28 @@ | ||
| 96 | 104 | return 0; |
| 97 | 105 | } |
| 98 | 106 | |
| 107 | +char* get_floatOperator(void){ | |
| 108 | + char* err; | |
| 109 | + int spos; | |
| 110 | + next_position(); | |
| 111 | + spos=g_srcpos; | |
| 112 | + err=get_operator(); | |
| 113 | + if (err) return err; | |
| 114 | + switch(g_last_op){ | |
| 115 | + // Following operators cannot be used for float values. | |
| 116 | + case OP_XOR: | |
| 117 | + case OP_REM: | |
| 118 | + case OP_SHR: | |
| 119 | + case OP_SHL: | |
| 120 | + g_srcpos=spos; | |
| 121 | + return ERR_SYNTAX; | |
| 122 | + default: | |
| 123 | + return 0; | |
| 124 | + } | |
| 125 | +} | |
| 126 | + | |
| 99 | 127 | char* calculation(enum operator op){ |
| 100 | - // $v0 = $v0 <op> $v1; | |
| 128 | + // $v0 = $v1 <op> $v0; | |
| 101 | 129 | switch(op){ |
| 102 | 130 | case OP_OR: |
| 103 | 131 | check_obj_space(1); |
| @@ -139,6 +167,14 @@ | ||
| 139 | 167 | g_object[g_objpos++]=0x0062102A; // slt v0,v1,v0 |
| 140 | 168 | g_object[g_objpos++]=0x38420001; // xori v0,v0,0x1 |
| 141 | 169 | break; |
| 170 | + case OP_SHR: | |
| 171 | + check_obj_space(1); | |
| 172 | + g_object[g_objpos++]=0x00431006; // srlv v0,v1,v0 | |
| 173 | + break; | |
| 174 | + case OP_SHL: | |
| 175 | + check_obj_space(1); | |
| 176 | + g_object[g_objpos++]=0x00431004; // sllv v0,v1,v0 | |
| 177 | + break; | |
| 142 | 178 | case OP_ADD: |
| 143 | 179 | check_obj_space(1); |
| 144 | 180 | g_object[g_objpos++]=0x00621021; // addu v0,v1,v0 |
| @@ -173,4 +209,67 @@ | ||
| 173 | 209 | return ERR_SYNTAX; |
| 174 | 210 | } |
| 175 | 211 | 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 |
| @@ -4,7 +4,8 @@ | ||
| 4 | 4 | http://www.ze.em-net.ne.jp/~kenken/index.html |
| 5 | 5 | */ |
| 6 | 6 | |
| 7 | -#define TBUFMAXLINE 101 //テキストバッファ数 | |
| 7 | +#define TBUFMAXLINE 201 //テキストバッファ数 | |
| 8 | + | |
| 8 | 9 | #define TBUFSIZE 200 //テキストバッファ1つのサイズ |
| 9 | 10 | #define TBUFMAXSIZE (TBUFSIZE*(TBUFMAXLINE-1)) //最大バッファ容量(バッファ1行分空ける) |
| 10 | 11 | #define EDITWIDTHX 30 //エディタ画面横幅 |
| @@ -21,9 +22,8 @@ | ||
| 21 | 22 | #define ERR_CANTWRITEFILE -3 |
| 22 | 23 | |
| 23 | 24 | #define TEMPFILENAME "~TEMP.BAS" |
| 24 | -#define INIFILE "MACHIKAN.INI" // 初期設定ファイル | |
| 25 | -#define HEXFILE "MACHIKAN.HEX" // 実行中HEXファイル名がこれと一致した場合はエディタ起動 | |
| 26 | 25 | |
| 27 | 26 | void texteditor(void); //テキストエディタ本体 |
| 28 | 27 | int runbasic(char *s,int test); //コンパイルして実行 |
| 29 | 28 | extern unsigned char tempfile[13]; |
| 29 | +void wait60thsec(unsigned short n); |
| @@ -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 | +} |
| @@ -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を返す |
| @@ -6,53 +6,107 @@ | ||
| 6 | 6 | */ |
| 7 | 7 | |
| 8 | 8 | #include <xc.h> |
| 9 | +#include "main.h" | |
| 9 | 10 | #include "compiler.h" |
| 10 | 11 | #include "api.h" |
| 11 | 12 | #include "keyinput.h" |
| 13 | +#include "stdlib.h" | |
| 14 | +#include "math.h" | |
| 12 | 15 | |
| 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; | |
| 15 | 26 | static unsigned int pos=0; |
| 16 | 27 | static unsigned int in_data=0; |
| 28 | + static unsigned char skip=0; | |
| 17 | 29 | if (label) { |
| 18 | 30 | // 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) { | |
| 21 | 77 | err_data_not_found(); |
| 22 | 78 | return 0; |
| 23 | 79 | } |
| 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; | |
| 27 | 84 | } 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++; | |
| 40 | 100 | } |
| 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; | |
| 50 | 102 | } |
| 51 | - in_data--; | |
| 52 | - return g_object[pos++]; | |
| 53 | - } | |
| 103 | + } | |
| 54 | 104 | } |
| 55 | 105 | |
| 106 | +void reset_dataread(){ | |
| 107 | + lib_read(2,1); | |
| 108 | +} | |
| 109 | + | |
| 56 | 110 | char* lib_midstr(int var_num, int pos, int len){ |
| 57 | 111 | int i; |
| 58 | 112 | char* str; |
| @@ -122,21 +176,13 @@ | ||
| 122 | 176 | } |
| 123 | 177 | |
| 124 | 178 | 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; | |
| 140 | 186 | } |
| 141 | 187 | |
| 142 | 188 | char* lib_chr(int num){ |
| @@ -332,7 +378,7 @@ | ||
| 332 | 378 | while(vkey!=0); |
| 333 | 379 | // Get string as a line |
| 334 | 380 | lineinput(str,63); |
| 335 | - if (g_disable_break==0 && (ps2keystatus[0x03] || (PORTB&0x4c80)==0)) err_break(); | |
| 381 | + check_break(); | |
| 336 | 382 | return str; |
| 337 | 383 | } |
| 338 | 384 |
| @@ -449,15 +495,356 @@ | ||
| 449 | 495 | for(i=0;i<period;i++){ |
| 450 | 496 | dcount=drawcount; |
| 451 | 497 | 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(); | |
| 454 | 500 | } |
| 455 | 501 | } |
| 456 | 502 | } |
| 457 | 503 | |
| 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 | + | |
| 458 | 841 | int _call_library(int a0,int a1,int a2,enum libs a3); |
| 459 | 842 | |
| 460 | 843 | 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 | |
| 461 | 848 | asm volatile("addu $a2,$v0,$zero"); |
| 462 | 849 | asm volatile("j _call_library"); |
| 463 | 850 | } |
| @@ -465,11 +852,12 @@ | ||
| 465 | 852 | int _call_library(int a0,int a1,int v0,enum libs a3){ |
| 466 | 853 | // usage: call_lib_code(LIB_XXXX); |
| 467 | 854 | // Above code takes 2 words. |
| 468 | - if (g_disable_break==0 && (ps2keystatus[0x03] || (PORTB&0x4c80)==0)) err_break(); | |
| 855 | + check_break(); | |
| 469 | 856 | 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); | |
| 473 | 861 | case LIB_STRNCMP: |
| 474 | 862 | return strncmp((char*)a0,(char*)a1,v0); |
| 475 | 863 | case LIB_MIDSTR: |
| @@ -491,13 +879,23 @@ | ||
| 491 | 879 | return (int)lib_connect_string((char*)a0, (char*)v0); |
| 492 | 880 | case LIB_STRING: |
| 493 | 881 | lib_string(a0); |
| 494 | - return; | |
| 882 | + return v0; | |
| 495 | 883 | case LIB_PRINTSTR: |
| 496 | 884 | 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; | |
| 498 | 896 | case LIB_SCROLL: |
| 499 | 897 | lib_scroll(a0,v0); |
| 500 | - return; | |
| 898 | + return v0; | |
| 501 | 899 | case LIB_KEYS: |
| 502 | 900 | return lib_keys(v0); |
| 503 | 901 | case LIB_INKEY: |
| @@ -504,56 +902,83 @@ | ||
| 504 | 902 | return (int)lib_inkey(v0); |
| 505 | 903 | case LIB_CURSOR: |
| 506 | 904 | setcursor(a0,v0,cursorcolor); |
| 507 | - return; | |
| 905 | + return v0; | |
| 508 | 906 | case LIB_SOUND: |
| 509 | 907 | set_sound((unsigned long*)v0); |
| 510 | - return; | |
| 908 | + return v0; | |
| 511 | 909 | case LIB_MUSICFUNC: |
| 512 | 910 | return musicRemaining(); |
| 513 | 911 | case LIB_MUSIC: |
| 514 | 912 | set_music((char*)v0); |
| 515 | - return; | |
| 913 | + return v0; | |
| 516 | 914 | case LIB_SETDRAWCOUNT: |
| 517 | 915 | drawcount=(v0&0x0000FFFF); |
| 518 | - return; | |
| 916 | + return v0; | |
| 519 | 917 | case LIB_DRAWCOUNT: |
| 520 | 918 | return drawcount; |
| 919 | + case LIB_SYSTEM: | |
| 920 | + return lib_system(a0,v0); | |
| 521 | 921 | 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); | |
| 524 | 925 | case LIB_READ: |
| 525 | - return lib_read(0); | |
| 926 | + return lib_read(0,0); | |
| 927 | + case LIB_CREAD: | |
| 928 | + return lib_read(1,0); | |
| 526 | 929 | case LIB_LABEL: |
| 527 | 930 | return (int)lib_label(v0); |
| 528 | 931 | case LIB_INPUT: |
| 529 | 932 | return (int)lib_input(); |
| 933 | + case LIB_USEGRAPHIC: | |
| 934 | + lib_usegraphic(v0); | |
| 935 | + return v0; | |
| 530 | 936 | case LIB_USEPCG: |
| 531 | 937 | lib_usepcg(v0); |
| 532 | - return; | |
| 938 | + return v0; | |
| 533 | 939 | case LIB_PCG: |
| 534 | 940 | lib_pcg(a0,a1,v0); |
| 535 | - return; | |
| 941 | + return v0; | |
| 536 | 942 | case LIB_BGCOLOR: // BGCOLOR R,G,B |
| 537 | 943 | set_bgcolor(v0,a0,a1); //set_bgcolor(b,r,g); |
| 538 | - return; | |
| 944 | + return v0; | |
| 539 | 945 | case LIB_PALETTE: // PALETTE N,R,G,B |
| 540 | 946 | 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; | |
| 542 | 951 | case LIB_CLS: |
| 543 | 952 | 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; | |
| 545 | 958 | case LIB_COLOR: |
| 546 | 959 | setcursorcolor(v0); |
| 547 | - return; | |
| 960 | + return v0; | |
| 961 | + case LIB_GCOLOR: | |
| 962 | + g_gcolor=v0; | |
| 963 | + return v0; | |
| 548 | 964 | case LIB_WAIT: |
| 549 | 965 | lib_wait(v0); |
| 550 | - return; | |
| 966 | + return v0; | |
| 551 | 967 | case LIB_CLEAR: |
| 552 | 968 | lib_clear(); |
| 553 | - return; | |
| 969 | + return v0; | |
| 554 | 970 | 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; | |
| 556 | 980 | default: |
| 557 | - break; | |
| 981 | + err_unknown(); | |
| 982 | + return v0; | |
| 558 | 983 | } |
| 559 | 984 | } |
| \ No newline at end of file |
| @@ -7,7 +7,8 @@ | ||
| 7 | 7 | |
| 8 | 8 | /* |
| 9 | 9 | Public functions: |
| 10 | - char* teg_string(void); | |
| 10 | + char* get_string(void); | |
| 11 | + char* simple_string(void); | |
| 11 | 12 | */ |
| 12 | 13 | |
| 13 | 14 | #include "api.h" |
| @@ -15,7 +16,7 @@ | ||
| 15 | 16 | |
| 16 | 17 | char* simple_string(void){ |
| 17 | 18 | char* err; |
| 18 | - char b1,b2; | |
| 19 | + unsigned char b1,b2; | |
| 19 | 20 | int i,j; |
| 20 | 21 | next_position(); |
| 21 | 22 | b1=g_source[g_srcpos]; |
| @@ -23,8 +24,21 @@ | ||
| 23 | 24 | if (b1=='"') { |
| 24 | 25 | // Constant string |
| 25 | 26 | // 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++; | |
| 28 | 42 | // Determine required word number |
| 29 | 43 | i=(i+3)/4; |
| 30 | 44 | // Determine address containing the string |
| @@ -34,9 +48,30 @@ | ||
| 34 | 48 | check_obj_space(2+i); |
| 35 | 49 | g_object[g_objpos++]=0x04110000|((i+1)&0x0000FFFF); // bgezal zero,xxxx |
| 36 | 50 | g_object[g_objpos++]=0x03E01021; // addu v0,ra,zero |
| 37 | - | |
| 38 | - | |
| 39 | 51 | for(j=0;(b1=g_source[g_srcpos++])!='"';j++) { |
| 52 | + if (b1=='\\') { | |
| 53 | + b1=g_source[g_srcpos++]; | |
| 54 | + if (b1=='x' || b1=='X') { | |
| 55 | + // Hexadecimal | |
| 56 | + b1=g_source[g_srcpos++]; | |
| 57 | + if ('0'<=b1 && b1<='9') b1=b1-'0'; | |
| 58 | + else if ('A'<=b1 && b1<='F') b1=b1-'A'+10; | |
| 59 | + else if ('a'<=b1 && b1<='f') b1=b1-'a'+10; | |
| 60 | + else return ERR_SYNTAX; | |
| 61 | + b2=g_source[g_srcpos++]; | |
| 62 | + if ('0'<=b2 && b2<='9') b2=b2-'0'; | |
| 63 | + else if ('A'<=b2 && b2<='F') b2=b2-'A'+10; | |
| 64 | + else if ('a'<=b2 && b2<='f') b2=b2-'a'+10; | |
| 65 | + else return ERR_SYNTAX; | |
| 66 | + b1=(b1<<4)|b2; | |
| 67 | + } else if (b1<0x20) { | |
| 68 | + return ERR_SYNTAX; | |
| 69 | + } else { | |
| 70 | + // \\ or \" | |
| 71 | + } | |
| 72 | + } else if (b1<0x20) { | |
| 73 | + return ERR_SYNTAX; | |
| 74 | + } | |
| 40 | 75 | ((char*)(&g_object[g_objpos]))[j]=b1; |
| 41 | 76 | } |
| 42 | 77 | ((char*)(&g_object[g_objpos]))[j]=0x00; |
| @@ -72,6 +107,8 @@ | ||
| 72 | 107 | g_sdepth-=4; |
| 73 | 108 | if (g_source[g_srcpos]!=')') return ERR_SYNTAX; |
| 74 | 109 | g_srcpos++; |
| 110 | + // Temp area will be used when executing. | |
| 111 | + g_temp_area_used=1; | |
| 75 | 112 | } else { |
| 76 | 113 | return ERR_SYNTAX; |
| 77 | 114 | } |
| @@ -89,7 +126,11 @@ | ||
| 89 | 126 | // Function |
| 90 | 127 | // String would be pointed by $v0 |
| 91 | 128 | // 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; | |
| 93 | 134 | } else { |
| 94 | 135 | return ERR_SYNTAX; |
| 95 | 136 | } |
| @@ -123,6 +164,8 @@ | ||
| 123 | 164 | check_obj_space(2); |
| 124 | 165 | g_object[g_objpos++]=0x8FA40000|g_sdepth; // lw a0,xx(sp) |
| 125 | 166 | call_lib_code(LIB_CONNECT_STRING); |
| 167 | + // Temp area will be used when executing. | |
| 168 | + g_temp_area_used=1; | |
| 126 | 169 | // Check if further connection operator exists |
| 127 | 170 | next_position(); |
| 128 | 171 | b1=g_source[g_srcpos]; |
| @@ -164,6 +207,7 @@ | ||
| 164 | 207 | g_object[g_objpos++]=0x27BD0000 | g_maxsdepth & 0x0000FFFF; // addiu sp,sp,xx |
| 165 | 208 | } |
| 166 | 209 | } |
| 210 | + g_lastvar=VAR_STRING; | |
| 167 | 211 | return 0; |
| 168 | 212 | } |
| 169 | 213 |
| @@ -14,6 +14,37 @@ | ||
| 14 | 14 | char* get_value(); |
| 15 | 15 | char* get_value_sub(int pr); |
| 16 | 16 | |
| 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 | +} | |
| 17 | 48 | |
| 18 | 49 | char* get_simple_value(void){ |
| 19 | 50 | int i; |
| @@ -39,6 +70,7 @@ | ||
| 39 | 70 | if (err) return err; |
| 40 | 71 | check_obj_space(1); |
| 41 | 72 | g_object[g_objpos++]=0x00021023; // subu v0,zero,v0 |
| 73 | + g_intconst=-g_intconst; | |
| 42 | 74 | } else { |
| 43 | 75 | // Main routine of getting value here |
| 44 | 76 | if (b1=='+') g_srcpos++; // Ignore unary '+' operator |
| @@ -63,6 +95,7 @@ | ||
| 63 | 95 | } |
| 64 | 96 | g_srcpos++; |
| 65 | 97 | } |
| 98 | + g_intconst=i; | |
| 66 | 99 | if (i&0xFFFF0000) { |
| 67 | 100 | // 32 bit |
| 68 | 101 | check_obj_space(2); |
| @@ -73,36 +106,23 @@ | ||
| 73 | 106 | check_obj_space(1); |
| 74 | 107 | g_object[g_objpos++]=0x34020000|(i&0x0000FFFF); // ori v0,zero,xxxx |
| 75 | 108 | } |
| 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 | + } | |
| 80 | 120 | 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 | - } | |
| 105 | 121 | } |
| 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; | |
| 106 | 126 | if (i&0xFFFF0000) { |
| 107 | 127 | // 32 bit |
| 108 | 128 | check_obj_space(2); |
| @@ -113,33 +133,27 @@ | ||
| 113 | 133 | check_obj_space(1); |
| 114 | 134 | g_object[g_objpos++]=0x34020000|(i&0x0000FFFF); // ori v0,zero,xxxx |
| 115 | 135 | } |
| 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(); | |
| 141 | 136 | } 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 | + } | |
| 143 | 157 | } |
| 144 | 158 | } |
| 145 | 159 | // No error |
| @@ -212,5 +226,46 @@ | ||
| 212 | 226 | g_object[g_objpos++]=0x27BD0000 | g_maxsdepth & 0x0000FFFF; // addiu sp,sp,xx |
| 213 | 227 | } |
| 214 | 228 | } |
| 229 | + g_lastvar=VAR_INTEGER; | |
| 215 | 230 | 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 | + |