emuapi.cpp
1 #define KEYMAP_PRESENT 1 2 3 extern "C" { 4 #include "emuapi.h" 5 #include "iopins.h" 6 } 7 8 #ifdef HAS_T4_VGA 9 #include "vga_t_dma.h" 10 #else 11 #include "tft_t_dma.h" 12 #endif 13 14 #ifdef HAS_USBKEY 15 #include "USBHost_t36.h" // Read this header first for key info 16 USBHost myusb; 17 USBHub hub1(myusb); 18 KeyboardController keyboard1(myusb); 19 USBHIDParser hid1(myusb); 20 MouseController mouse1(myusb); 21 MIDIDevice midi1(myusb); 22 #endif 23 24 static bool emu_writeConfig(void); 25 static bool emu_readConfig(void); 26 static bool emu_eraseConfig(void); 27 28 static bool mouseDetected = false; 29 static bool keyboardDetected = false; 30 static uint8_t usbnavpad=0; 31 32 #include <SD.h> 33 static File file; 34 35 #define MAX_FILES 64 36 #define AUTORUN_FILENAME "autorun.txt" 37 38 #define MAX_FILENAME_SIZE 24 39 #define MAX_MENULINES 9 40 #define TEXT_HEIGHT 16 41 #define TEXT_WIDTH 8 42 #define MENU_FILE_XOFFSET (6*TEXT_WIDTH) 43 #define MENU_FILE_YOFFSET (2*TEXT_HEIGHT) 44 #define MENU_FILE_W (MAX_FILENAME_SIZE*TEXT_WIDTH) 45 #define MENU_FILE_H (MAX_MENULINES*TEXT_HEIGHT) 46 #define MENU_FILE_BGCOLOR RGBVAL16(0x00,0x00,0x40) 47 #define MENU_JOYS_YOFFSET (12*TEXT_HEIGHT) 48 #define MENU_VBAR_XOFFSET (0*TEXT_WIDTH) 49 #define MENU_VBAR_YOFFSET (MENU_FILE_YOFFSET) 50 51 #define MENU_TFT_XOFFSET (MENU_FILE_XOFFSET+MENU_FILE_W+8) 52 #define MENU_TFT_YOFFSET (MENU_VBAR_YOFFSET+32) 53 #define MENU_VGA_XOFFSET (MENU_FILE_XOFFSET+MENU_FILE_W+8) 54 #define MENU_VGA_YOFFSET (MENU_VBAR_YOFFSET+MENU_FILE_H-32-37) 55 56 extern TFT_T_DMA tft; 57 58 static int nbFiles=0; 59 static int curFile=0; 60 static int topFile=0; 61 static char selection[MAX_FILENAME_PATH]=""; 62 static char second_selection[MAX_FILENAME_PATH]=""; 63 static char files[MAX_FILES][MAX_FILENAME_SIZE]; 64 static char selected_filename[MAX_FILENAME_SIZE]=""; 65 static char second_selected_filename[MAX_FILENAME_SIZE]=""; 66 static bool menuRedraw=true; 67 static bool autorun=false; 68 69 static const unsigned short * keys; 70 #ifdef TEECOMPUTER 71 static unsigned char keymatrix[6]; 72 static int keymatrix_hitrow=-1; 73 static uint32_t keypress_t_ms=0; 74 static uint32_t last_t_ms=0; 75 static uint32_t hundred_ms_cnt=0; 76 static bool ledflash_toggle=false; 77 #endif 78 static bool key_extmode=false; 79 static bool key_sh=false; 80 static bool key_fn=false; 81 82 static boolean joySwapped = false; 83 static uint16_t bLastState; 84 #ifdef PIN_JOY2_A1X 85 static int xRef; 86 static int yRef; 87 #endif 88 static bool menuOn=true; 89 90 91 /******************************** 92 * Generic output and malloc 93 ********************************/ 94 void emu_printf(const char * text) 95 { 96 Serial.println(text); 97 } 98 99 void emu_printf(int val) 100 { 101 Serial.println(val); 102 } 103 104 void emu_printi(int val) 105 { 106 Serial.println(val,HEX); 107 } 108 109 void emu_printh(int val) 110 { 111 Serial.println(val,HEX); 112 } 113 114 static int malbufpt = 0; 115 static char malbuf[EXTRA_HEAP]; 116 117 void * emu_Malloc(unsigned int size) 118 { 119 void * retval = malloc(size); 120 if (!retval) { 121 emu_printf("failled to allocate"); 122 emu_printf(size); 123 emu_printf("fallback"); 124 if ( (malbufpt+size) < sizeof(malbuf) ) { 125 retval = (void *)&malbuf[malbufpt]; 126 malbufpt += size; 127 } 128 else { 129 emu_printf("failure to allocate"); 130 } 131 } 132 else { 133 emu_printf("could allocate dynamic "); 134 emu_printf(size); 135 } 136 137 return retval; 138 } 139 140 void * emu_MallocI(unsigned int size) 141 { 142 void * retval = NULL; 143 144 if ( (malbufpt+size) < sizeof(malbuf) ) { 145 retval = (void *)&malbuf[malbufpt]; 146 malbufpt += size; 147 emu_printf("could allocate static "); 148 emu_printf(size); 149 } 150 else { 151 emu_printf("failure to allocate"); 152 } 153 154 return retval; 155 } 156 void emu_Free(void * pt) 157 { 158 free(pt); 159 } 160 161 /******************************** 162 * Input and keyboard 163 ********************************/ 164 #ifdef PIN_JOY2_A1X 165 int emu_ReadAnalogJoyX(int min, int max) 166 { 167 int val = analogRead(PIN_JOY2_A1X); 168 #if INVX 169 val = 4095 - val; 170 #endif 171 val = val-xRef; 172 val = ((val*140)/100); 173 if ( (val > -512) && (val < 512) ) val = 0; 174 val = val+2048; 175 return (val*(max-min))/4096; 176 } 177 #endif 178 179 #ifdef PIN_JOY2_A2Y 180 int emu_ReadAnalogJoyY(int min, int max) 181 { 182 int val = analogRead(PIN_JOY2_A2Y); 183 #if INVY 184 val = 4095 - val; 185 #endif 186 val = val-yRef; 187 val = ((val*120)/100); 188 if ( (val > -512) && (val < 512) ) val = 0; 189 //val = (val*(max-min))/4096; 190 val = val+2048; 191 //return val+(max-min)/2; 192 return (val*(max-min))/4096; 193 } 194 #endif 195 196 static uint16_t readAnalogJoystick(void) 197 { 198 uint16_t joysval = 0; 199 200 #ifdef PIN_JOY2_A1X 201 int xReading = emu_ReadAnalogJoyX(0,256); 202 if (xReading > 128) joysval |= MASK_JOY2_LEFT; 203 else if (xReading < 128) joysval |= MASK_JOY2_RIGHT; 204 205 int yReading = emu_ReadAnalogJoyY(0,256); 206 if (yReading < 128) joysval |= MASK_JOY2_UP; 207 else if (yReading > 128) joysval |= MASK_JOY2_DOWN; 208 #endif 209 210 #ifdef PIN_JOY2_BTN 211 joysval |= (digitalRead(PIN_JOY2_BTN) == HIGH ? 0 : MASK_JOY2_BTN); 212 #endif 213 return (joysval); 214 } 215 216 217 int emu_SwapJoysticks(int statusOnly) { 218 if (!statusOnly) { 219 if (joySwapped) { 220 joySwapped = false; 221 } 222 else { 223 joySwapped = true; 224 } 225 } 226 return(joySwapped?1:0); 227 } 228 229 int emu_GetPad(void) 230 { 231 return(bLastState/*|((joySwapped?1:0)<<7)*/); 232 } 233 234 int emu_ReadKeys(void) 235 { 236 uint16_t retval; 237 uint16_t j1 = readAnalogJoystick(); 238 uint16_t j2 = 0; 239 240 // Second joystick 241 #ifdef PIN_JOY1_1 242 if ( digitalRead(PIN_JOY1_1) == LOW ) j2 |= MASK_JOY2_UP; 243 #endif 244 #ifdef PIN_JOY1_2 245 if ( digitalRead(PIN_JOY1_2) == LOW ) j2 |= MASK_JOY2_DOWN; 246 #endif 247 #ifdef PIN_JOY1_3 248 if ( digitalRead(PIN_JOY1_3) == LOW ) j2 |= MASK_JOY2_RIGHT; 249 #endif 250 #ifdef PIN_JOY1_4 251 if ( digitalRead(PIN_JOY1_4) == LOW ) j2 |= MASK_JOY2_LEFT; 252 #endif 253 #ifdef PIN_JOY1_BTN 254 if ( digitalRead(PIN_JOY1_BTN) == LOW ) j2 |= MASK_JOY2_BTN; 255 #endif 256 if (joySwapped) { 257 retval = ((j1 << 8) | j2); 258 } 259 else { 260 retval = ((j2 << 8) | j1); 261 } 262 263 if (usbnavpad & MASK_JOY2_UP) retval |= MASK_JOY2_UP; 264 if (usbnavpad & MASK_JOY2_DOWN) retval |= MASK_JOY2_DOWN; 265 if (usbnavpad & MASK_JOY2_LEFT) retval |= MASK_JOY2_LEFT; 266 if (usbnavpad & MASK_JOY2_RIGHT) retval |= MASK_JOY2_RIGHT; 267 if (usbnavpad & MASK_JOY2_BTN) retval |= MASK_JOY2_BTN; 268 if (usbnavpad & MASK_KEY_USER1) retval |= MASK_KEY_USER1; 269 if (usbnavpad & MASK_KEY_USER2) retval |= MASK_KEY_USER2; 270 271 #ifdef PIN_KEY_USER1 272 if ( digitalRead(PIN_KEY_USER1) == LOW ) retval |= MASK_KEY_USER1; 273 #endif 274 #ifdef PIN_KEY_USER2 275 if ( digitalRead(PIN_KEY_USER2) == LOW ) retval |= MASK_KEY_USER2; 276 #endif 277 #ifdef PIN_KEY_USER3 278 if ( digitalRead(PIN_KEY_USER3) == LOW ) retval |= MASK_KEY_USER3; 279 #endif 280 #ifdef PIN_KEY_USER4 281 if ( digitalRead(PIN_KEY_USER4) == LOW ) retval |= MASK_KEY_USER4; 282 #endif 283 284 #ifdef TEECOMPUTER 285 keymatrix_hitrow = -1; 286 unsigned char row; 287 unsigned short cols[6]={KCOLOUT1,KCOLOUT2,KCOLOUT3,KCOLOUT4,KCOLOUT5,KCOLOUT6}; 288 for (int i=0;i<6;i++){ 289 pinMode(cols[i],OUTPUT); 290 digitalWrite(cols[i], 0); 291 row=0; 292 row |= (digitalRead(KROWIN1) ? 0 : 0x01); 293 row |= (digitalRead(KROWIN2) ? 0 : 0x02); 294 row |= (digitalRead(KROWIN3) ? 0 : 0x04); 295 row |= (digitalRead(KROWIN4) ? 0 : 0x08); 296 row |= (digitalRead(KROWIN5) ? 0 : 0x10); 297 row |= (digitalRead(KROWIN6) ? 0 : 0x20); 298 row |= (digitalRead(KROWIN7) ? 0 : 0x40); 299 digitalWrite(cols[i], 1); 300 pinMode(cols[i],INPUT_DISABLE); 301 keymatrix[i]=row; 302 } 303 304 bool fn_pressed=false; 305 if ( keymatrix[5] & 0x08 ) {fn_pressed=true; keymatrix[5] &= ~0x08;}; 306 307 bool sh_pressed=false; 308 if ( keymatrix[5] & 0x10 ) {sh_pressed=true; keymatrix[5] &= ~0x10;}; 309 310 for (int i=0;i<6;i++){ 311 row = keymatrix[i]; 312 if (row) keymatrix_hitrow=i; 313 } 314 315 //6,9,15,8,7,22 316 #if INVX 317 if ( row & 0x40 ) retval |= MASK_JOY2_LEFT; 318 if ( row & 0x20 ) retval |= MASK_JOY2_RIGHT; 319 #else 320 if ( row & 0x20 ) retval |= MASK_JOY2_LEFT; 321 if ( row & 0x40 ) retval |= MASK_JOY2_RIGHT; 322 #endif 323 #if INVY 324 if ( row & 0x4 ) retval |= MASK_JOY2_DOWN; 325 if ( row & 0x1 ) retval |= MASK_JOY2_UP; 326 #else 327 if ( row & 0x1 ) retval |= MASK_JOY2_DOWN; 328 if ( row & 0x4 ) retval |= MASK_JOY2_UP; 329 #endif 330 if ( row & 0x02 ) retval |= MASK_JOY2_BTN; 331 332 // Handle LED flash 333 uint32_t time_ms=millis(); 334 if ((time_ms-last_t_ms) > 100) { 335 last_t_ms = time_ms; 336 if (ledflash_toggle == false) { 337 ledflash_toggle = true; 338 } 339 else { 340 ledflash_toggle = false; 341 } 342 } 343 344 if ( sh_pressed ) { 345 key_sh = true; 346 } 347 else { 348 key_sh = false; 349 if ( fn_pressed ) { 350 if (key_fn == false) 351 { 352 // Release to Press transition 353 if (hundred_ms_cnt == 0) { 354 keypress_t_ms=time_ms; 355 hundred_ms_cnt += 1; // 1 356 } 357 else { 358 hundred_ms_cnt += 1; // 2 359 if (hundred_ms_cnt >= 2) 360 { 361 hundred_ms_cnt = 0; 362 if ( (time_ms-keypress_t_ms) < 500) 363 { 364 if (key_extmode == false) 365 { 366 key_extmode = true; 367 } 368 else 369 { 370 key_extmode = false; 371 } 372 } 373 } 374 } 375 } 376 else { 377 // Keep press 378 if (hundred_ms_cnt == 1) { 379 if ((millis()-keypress_t_ms) > 1000) 380 { 381 if (key_extmode == false) 382 { 383 key_extmode = true; 384 } 385 else 386 { 387 key_extmode = false; 388 } 389 hundred_ms_cnt = 0; 390 } 391 } 392 } 393 key_fn = true; 394 } 395 else { 396 key_fn = false; 397 } 398 } 399 400 // Handle LED 401 if (key_extmode == true) { 402 digitalWrite(KLED, (ledflash_toggle?1:0)); 403 } 404 else { 405 if ( (key_fn == true) || (key_sh == true) ) { 406 digitalWrite(KLED, 1); 407 } 408 else { 409 digitalWrite(KLED, 0); 410 } 411 } 412 413 if ( key_fn ) retval |= MASK_KEY_USER2; 414 if ( ( key_fn ) && (keymatrix[4] == 0x10 )) retval |= MASK_KEY_USER1; 415 416 if ( (key_fn) && (key_sh) ) 417 #else 418 if ( ((retval & (MASK_KEY_USER1+MASK_KEY_USER2)) == (MASK_KEY_USER1+MASK_KEY_USER2)) 419 || (retval & MASK_KEY_USER4 ) ) 420 #endif 421 { 422 // Reset procedure T3.X and T4.0 by Frank Boesing !! 423 #if defined(__IMXRT1052__) || defined(__IMXRT1062__) 424 uint32_t tmp = SNVS_LPCR; // save control register 425 426 SNVS_LPSR |= 1; 427 428 // disable alarm 429 SNVS_LPCR &= ~0x02; 430 while (SNVS_LPCR & 0x02); 431 432 __disable_irq(); 433 //get Time: 434 uint32_t lsb, msb; 435 do { 436 msb = SNVS_LPSRTCMR; 437 lsb = SNVS_LPSRTCLR; 438 } while ( (SNVS_LPSRTCLR != lsb) | (SNVS_LPSRTCMR != msb) ); 439 uint32_t secs = (msb << 17) | (lsb >> 15); 440 441 //set alarm 442 secs += 2; 443 SNVS_LPTAR = secs; 444 while (SNVS_LPTAR != secs); 445 446 SNVS_LPCR = tmp | 0x02; // restore control register and set alarm 447 while (!(SNVS_LPCR & 0x02)); 448 449 SNVS_LPCR |= (1 << 6); // turn off power 450 while (1) asm("wfi"); 451 #else 452 *(volatile uint32_t *)0xE000ED0C = 0x5FA0004; 453 while (true) { 454 ; 455 } 456 #endif 457 } 458 459 return (retval); 460 } 461 462 unsigned short emu_DebounceLocalKeys(void) 463 { 464 uint16_t bCurState = emu_ReadKeys(); 465 uint16_t bClick = bCurState & ~bLastState; 466 bLastState = bCurState; 467 468 return (bClick); 469 } 470 471 int emu_ReadI2CKeyboard(void) { 472 int retval=0; 473 #ifdef TEECOMPUTER 474 if (key_extmode) { 475 if (key_fn) { 476 keys = (const unsigned short *)key_map5; // fn-extra 477 } 478 else if (key_sh) { 479 keys = (const unsigned short *)key_map4; // shift-functionkeys 480 } 481 else { 482 keys = (const unsigned short *)key_map3; // def-digitkeys 483 } 484 } 485 else { 486 if (key_fn) { 487 keys = (const unsigned short *)key_map2; // fn-shiftothers 488 } 489 else if (key_sh) { 490 keys = (const unsigned short *)key_map1; // shift-uppercase 491 } 492 else { 493 keys = (const unsigned short *)key_map0; // def-lowercase 494 } 495 } 496 497 498 if (keymatrix_hitrow >=0 ) { 499 unsigned short match = ((unsigned short)keymatrix_hitrow<<8) | keymatrix[keymatrix_hitrow]; 500 for (unsigned int i=0; i<sizeof(matkeys)/sizeof(unsigned short); i++) { 501 if (match == matkeys[i]) { 502 hundred_ms_cnt = 0; 503 return (keys[i]); 504 } 505 } 506 } 507 #endif 508 return(retval); 509 } 510 511 unsigned char emu_ReadI2CKeyboard2(int row) { 512 int retval=0; 513 #ifdef TEECOMPUTER 514 retval = keymatrix[row]; 515 #endif 516 return retval; 517 } 518 519 void emu_InitJoysticks(void) { 520 521 // Second Joystick 522 #ifdef PIN_JOY1_1 523 pinMode(PIN_JOY1_1, INPUT_PULLUP); 524 #endif 525 #ifdef PIN_JOY1_2 526 pinMode(PIN_JOY1_2, INPUT_PULLUP); 527 #endif 528 #ifdef PIN_JOY1_3 529 pinMode(PIN_JOY1_3, INPUT_PULLUP); 530 #endif 531 #ifdef PIN_JOY1_4 532 pinMode(PIN_JOY1_4, INPUT_PULLUP); 533 #endif 534 #ifdef PIN_JOY1_BTN 535 pinMode(PIN_JOY1_BTN, INPUT_PULLUP); 536 #endif 537 538 #ifdef PIN_KEY_USER1 539 pinMode(PIN_KEY_USER1, INPUT_PULLUP); 540 #endif 541 #ifdef PIN_KEY_USER2 542 pinMode(PIN_KEY_USER2, INPUT_PULLUP); 543 #endif 544 #ifdef PIN_KEY_USER3 545 pinMode(PIN_KEY_USER3, INPUT_PULLUP); 546 #endif 547 #ifdef PIN_KEY_USER4 548 pinMode(PIN_KEY_USER4, INPUT_PULLUP); 549 #endif 550 #ifdef PIN_JOY2_BTN 551 pinMode(PIN_JOY2_BTN, INPUT_PULLUP); 552 #endif 553 554 #ifdef PIN_JOY2_A1X 555 analogReadResolution(12); 556 xRef=0; yRef=0; 557 for (int i=0; i<10; i++) { 558 xRef += analogRead(PIN_JOY2_A1X); 559 yRef += analogRead(PIN_JOY2_A2Y); 560 delay(20); 561 } 562 #if INVX 563 xRef = 4095 -xRef/10; 564 #else 565 xRef /= 10; 566 #endif 567 #if INVY 568 yRef = 4095 -yRef/10; 569 #else 570 yRef /= 10; 571 #endif 572 #endif 573 574 #ifdef TEECOMPUTER 575 // keyboard LED 576 pinMode(KLED,OUTPUT); 577 digitalWrite(KLED,1); 578 579 // Output (cols) 580 pinMode(KCOLOUT1,OUTPUT); 581 pinMode(KCOLOUT2,OUTPUT); 582 pinMode(KCOLOUT3,OUTPUT); 583 pinMode(KCOLOUT4,OUTPUT); 584 pinMode(KCOLOUT5,OUTPUT); 585 pinMode(KCOLOUT6,OUTPUT); 586 digitalWrite(KCOLOUT1,1); 587 digitalWrite(KCOLOUT2,1); 588 digitalWrite(KCOLOUT3,1); 589 digitalWrite(KCOLOUT4,1); 590 digitalWrite(KCOLOUT5,1); 591 digitalWrite(KCOLOUT6,1); 592 593 // Input pins (rows) 594 pinMode(KROWIN1, INPUT_PULLUP); 595 pinMode(KROWIN2, INPUT_PULLUP); 596 pinMode(KROWIN3, INPUT_PULLUP); 597 pinMode(KROWIN4, INPUT_PULLUP); 598 pinMode(KROWIN5, INPUT_PULLUP); 599 pinMode(KROWIN6, INPUT_PULLUP); 600 pinMode(KROWIN7, INPUT_PULLUP); 601 #endif 602 } 603 604 605 int emu_setKeymap(int index) { 606 return 0; 607 } 608 609 int emu_GetMouse(int *x, int *y, int *buts) { 610 #ifdef HAS_USBKEY 611 if (mouse1.available()) { 612 *buts = mouse1.getButtons(); 613 *x = mouse1.getMouseX(); 614 *y = mouse1.getMouseY(); 615 mouse1.mouseDataClear(); 616 mouseDetected = true; 617 return 1; 618 } 619 #endif 620 return 0; 621 } 622 623 #ifdef HAS_USBKEY 624 void OnPress(auto key) 625 { 626 keyboardDetected = true; 627 uint8_t keymodifier = keyboard1.getModifiers(); 628 629 if(keymodifier == 0x40){ 630 // ALTGR Key modifier FR Keyboard 631 switch (key) { 632 #ifdef LAYOUT_FRENCH 633 case 233 : key = '~' ; break; 634 case 34 : key = '#' ; break; 635 case 39 : key = '{' ; break; 636 case 40 : key = '[' ; break; 637 case 45 : key = '|' ; break; 638 case 232 : key = '`' ; break; 639 case 95 : key = 92 ; break; 640 case 231 : key = '^' ; break; 641 case 224 : key = '@' ; break; 642 case 41 : key = ']' ; break; 643 case 61 : key = '}' ; break; 644 #endif 645 #ifdef LAYOUT_FRENCH_BELGIAN 646 case 38 : key = '|' ; break; //1 647 case 233 : key = '@' ; break; //2 648 case 34 : key = '#' ; break; //3 649 case 167 : key = '^' ; break; //6 650 case 231 : key = '{' ; break; //9 651 case 224 : key = '}' ; break; //0 652 case 36 : key = ']' ; break; //$ 653 case 61 : key = '~' ; break; //= 654 #endif 655 } 656 } 657 658 if (menuActive()) 659 { 660 switch (key) 661 { 662 case 217: 663 usbnavpad |= MASK_JOY2_DOWN; 664 break; 665 case 218: 666 usbnavpad |= MASK_JOY2_UP; 667 break; 668 case 216: 669 usbnavpad |= MASK_JOY2_LEFT; 670 break; 671 case 215: 672 usbnavpad |= MASK_JOY2_RIGHT; 673 break; 674 case 10: 675 usbnavpad |= MASK_JOY2_BTN; 676 break; 677 case 32: 678 usbnavpad |= MASK_KEY_USER1; 679 break; 680 case 9: 681 usbnavpad |= MASK_KEY_USER2; 682 break; 683 } 684 } 685 else 686 { 687 emu_KeyboardOnDown(keymodifier, key); 688 } 689 } 690 691 void OnRelease(int key) 692 { 693 keyboardDetected = true; 694 uint8_t keymodifier = keyboard1.getModifiers(); 695 696 if(keymodifier == 0x40){ 697 // ALTGR Key modifier FR Keyboard 698 switch (key) { 699 #ifdef LAYOUT_FRENCH 700 case 233 : key = '~' ; break; 701 case 34 : key = '#' ; break; 702 case 39 : key = '{' ; break; 703 case 40 : key = '[' ; break; 704 case 45 : key = '|' ; break; 705 case 232 : key = '`' ; break; 706 case 95 : key = 92 ; break; 707 case 231 : key = '^' ; break; 708 case 224 : key = '@' ; break; 709 case 41 : key = ']' ; break; 710 case 61 : key = '}' ; break; 711 #endif 712 #ifdef LAYOUT_FRENCH_BELGIAN 713 case 38 : key = '|' ; break; //1 714 case 233 : key = '@' ; break; //2 715 case 34 : key = '#' ; break; //3 716 case 167 : key = '^' ; break; //6 717 case 231 : key = '{' ; break; //9 718 case 224 : key = '}' ; break; //0 719 case 36 : key = ']' ; break; //$ 720 case 61 : key = '~' ; break; //= 721 #endif 722 } 723 } 724 725 if (menuActive()) 726 { 727 switch (key) 728 { 729 case 217: 730 usbnavpad &= ~MASK_JOY2_DOWN; 731 break; 732 case 218: 733 usbnavpad &= ~MASK_JOY2_UP; 734 break; 735 case 216: 736 usbnavpad &= ~MASK_JOY2_LEFT; 737 break; 738 case 215: 739 usbnavpad &= ~MASK_JOY2_RIGHT; 740 break; 741 case 10: 742 usbnavpad &= ~MASK_JOY2_BTN; 743 break; 744 case 32: 745 usbnavpad &= ~MASK_KEY_USER1; 746 break; 747 case 9: 748 usbnavpad &= ~MASK_KEY_USER2; 749 break; 750 } 751 } 752 else 753 { 754 emu_KeyboardOnUp(keymodifier, key); 755 } 756 } 757 #endif 758 759 int emu_MouseDetected(void) { 760 return (mouseDetected?1:0); 761 } 762 763 int emu_KeyboardDetected(void) { 764 return (keyboardDetected?1:0); 765 } 766 767 #ifdef HAS_USBKEY 768 static unsigned char midiBuffer[16]; 769 static unsigned char midiLastCmd=0; 770 static int midiDataCnt=0; 771 static int midiCmdNbParam=0; 772 #endif 773 774 void emu_MidiOnDataReceived(unsigned char value) { 775 776 #ifdef HAS_USBKEY 777 //Serial.println(value, HEX); 778 //10000000 = 128 = note off 779 //10010000 = 144 = note on 780 //10100000 = 160 = aftertouch 781 //10110000 = 176 = continuous controller 782 //11000000 = 192 = patch change 783 //11010000 = 208 = channel pressure 784 //11100000 = 224 = pitch bend 785 //11110000 = 240 = non-musical commands 786 if (value >= 128) { 787 midiDataCnt = 0; 788 midiLastCmd = value; 789 switch (value & 0xF0) { 790 case 128: // 0x80 791 midiCmdNbParam = 2; 792 //Serial.print("note off: "); 793 //Serial.println(value&0xf); 794 break; 795 case 144: //0x90 796 midiCmdNbParam = 2; 797 //Serial.print("note on: "); 798 //Serial.println(value&0xf); 799 break; 800 case 160: //0xA0 801 midiCmdNbParam = 2; 802 //Serial.print("aftertouch: "); // rare 803 //Serial.println(value&0xf); 804 break; 805 case 176: //0xB0 806 midiCmdNbParam = 2; 807 //Serial.print("continuous controller: "); 808 //Serial.println(value&0xf); 809 break; 810 case 192: //0xC0 811 midiCmdNbParam = 1; 812 //Serial.print("patch change: "); //some 813 //Serial.println(value&0xf); 814 break; 815 case 208: //0xD0 816 midiCmdNbParam = 1; 817 Serial.print("channel pressure: "); 818 Serial.println(value&0xf); 819 break; 820 case 224: //0xE0 821 midiCmdNbParam = 2; 822 //Serial.print("pitch bend: "); 823 //Serial.println(value&0xf); 824 break; 825 case 240: //0xF0 826 // non-musical commands 827 switch (value) { 828 case 0xF0: 829 //Serial.println("NI: System Exclusive"); 830 break; 831 case 0xF1: 832 //Serial.println("NI: System Common - MIDI Time Code Quarter Frame"); 833 break; 834 case 0xF2: 835 midiCmdNbParam = 2; 836 break; 837 case 0xF3: 838 //Serial.println("NI: System Common - Song Select"); 839 break; 840 case 0xF6: 841 //Serial.println("NI: System Common - Tune Request"); 842 break; 843 case 0xF8: 844 //Serial.println("System Real Time - Timing Clock"); 845 midi1.sendRealTime(value, 0); 846 break; 847 case 0xFA: 848 //Serial.println("System Real Time - Start"); 849 midi1.sendRealTime(value, 0); 850 break; 851 case 0xFB: 852 //Serial.println("System Real Time - Continue"); 853 midi1.sendRealTime(value, 0); 854 break; 855 case 0xFC: 856 //Serial.println("System Real Time - Stop"); 857 midi1.sendRealTime(value, 0); 858 break; 859 case 0xFE: 860 //Serial.println("System Real Time - Active Sensing"); 861 midi1.sendRealTime(value, 0); 862 break; 863 case 0xFF: 864 //Serial.println("System Real Time - System Reset"); 865 midi1.sendRealTime(value, 0); 866 break; 867 } 868 //SystemExclusive = 0xF0, // System Exclusive 869 //TimeCodeQuarterFrame = 0xF1, // System Common - MIDI Time Code Quarter Frame 870 //SongPosition = 0xF2, // System Common - Song Position Pointer 871 //SongSelect = 0xF3, // System Common - Song Select 872 //TuneRequest = 0xF6, // System Common - Tune Request 873 //Clock = 0xF8, // System Real Time - Timing Clock 874 //Start = 0xFA, // System Real Time - Start 875 //Continue = 0xFB, // System Real Time - Continue 876 //Stop = 0xFC, // System Real Time - Stop 877 //ActiveSensing = 0xFE, // System Real Time - Active Sensing 878 //SystemReset = 0xFF, // System Real Time - System Reset 879 break; 880 default: 881 Serial.print("??: "); 882 Serial.println(value&0xf); 883 break; 884 } 885 } 886 else { 887 if (midiDataCnt<16) midiBuffer[midiDataCnt++] = value ; 888 if ( (midiLastCmd & 0xF0) == 240) { 889 if (midiLastCmd == 0xF2) { 890 if (midiDataCnt == midiCmdNbParam) { 891 //Serial.println("System Common - Song Position Pointer"); 892 midi1.sendSongPosition(((int)midiBuffer[1]<<7)+(int)midiBuffer[0], 0); 893 } 894 } 895 else { 896 Serial.println(value); 897 } 898 } 899 else if (midiDataCnt == midiCmdNbParam) { 900 unsigned char chan = (midiLastCmd&0xf)+1; 901 //Serial.print("ch "); 902 //Serial.println(chan); 903 switch (midiLastCmd & 0xF0) { 904 case 128: //0x80 905 //Serial.print("note off: "); 906 midi1.sendNoteOff(midiBuffer[0], midiBuffer[1], chan); 907 break; 908 case 144: //0x90 909 //Serial.print("note on: "); 910 midi1.sendNoteOn(midiBuffer[0], midiBuffer[1], chan); 911 break; 912 case 160: //0xA0 913 //Serial.print("aftertouch: "); 914 midi1.sendPolyPressure(midiBuffer[0], midiBuffer[1], chan); 915 break; 916 case 176: //0xB0 917 //Serial.print("continuous controller: "); 918 midi1.sendControlChange(midiBuffer[0], midiBuffer[1], chan); 919 break; 920 case 192: //0xC0 921 //Serial.print("patch change: "); 922 midi1.sendProgramChange(midiBuffer[0], chan); 923 break; 924 case 208: //0xD0 925 //Serial.print("channel pressure: "); 926 midi1.sendAfterTouch(midiBuffer[0], chan); 927 break; 928 case 224: //0xE0 929 //Serial.print("pitch bend: "); 930 midi1.sendPitchBend((((int)midiBuffer[1]<<7)+(int)midiBuffer[0])-8192, chan); 931 break; 932 default: 933 Serial.print("??: "); 934 break; 935 } 936 } 937 } 938 #endif 939 } 940 941 /******************************** 942 * Menu file loader UI 943 ********************************/ 944 static int readNbFiles(void) { 945 int totalFiles = 0; 946 947 File entry; 948 file = SD.open(selection); 949 while ( (true) && (totalFiles<MAX_FILES) ) { 950 entry = file.openNextFile(); 951 if (! entry) { 952 // no more files 953 break; 954 } 955 const char * filename = entry.name(); 956 Serial.println(filename); 957 if (!entry.isDirectory()) { 958 strncpy(&files[totalFiles][0], filename, MAX_FILENAME_SIZE-1); 959 totalFiles++; 960 } 961 else { 962 if ( (strcmp(filename,".")) && (strcmp(filename,"..")) ) { 963 strncpy(&files[totalFiles][0], filename, MAX_FILENAME_SIZE-1); 964 totalFiles++; 965 } 966 } 967 entry.close(); 968 } 969 file.close(); 970 return totalFiles; 971 } 972 973 974 975 void backgroundMenu(void) { 976 menuRedraw=true; 977 tft.fillScreenNoDma(RGBVAL16(0x00,0x00,0x00)); 978 tft.drawTextNoDma(0,0, TITLE, RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), true); 979 } 980 981 int handleMenu(uint16_t bClick) 982 { 983 if (autorun) { 984 return (ACTION_RUN1); 985 } 986 987 int action = ACTION_NONE; 988 if ( (bClick & MASK_JOY2_BTN) || (bClick & MASK_JOY1_BTN) ) { 989 char newpath[MAX_FILENAME_PATH]; 990 strcpy(newpath, selection); 991 strcat(newpath, "/"); 992 strcat(newpath, selected_filename); 993 strcpy(selection,newpath); 994 emu_printf("new filepath is"); 995 emu_printf(selection); 996 File file = SD.open(selection); 997 if (file.isDirectory()) { 998 curFile = 0; 999 nbFiles = readNbFiles(); 1000 } 1001 else { 1002 action = ACTION_RUN1; 1003 #ifdef TEECOMPUTER 1004 if (key_extmode) { 1005 emu_writeConfig(); 1006 } 1007 #endif 1008 } 1009 menuRedraw=true; 1010 } 1011 else if ( bClick & MASK_KEY_USER1 ) { 1012 menuRedraw=true; 1013 strcpy(second_selected_filename,selected_filename); 1014 strcpy(second_selection, selection); 1015 strcat(second_selection, "/"); 1016 strcat(second_selection, second_selected_filename); 1017 action = ACTION_RUN2; 1018 } 1019 else if ( bClick & MASK_KEY_USER2 ) { 1020 menuRedraw=true; 1021 //action = ACTION_RUN3; 1022 emu_SwapJoysticks(0); 1023 } 1024 else if ( (bClick & MASK_JOY2_UP) || (bClick & MASK_JOY1_UP) ) { 1025 if (curFile!=0) { 1026 menuRedraw=true; 1027 curFile--; 1028 } 1029 } 1030 else if ( (bClick & MASK_JOY2_RIGHT) || (bClick & MASK_JOY1_RIGHT) ) { 1031 if ((curFile-9)>=0) { 1032 menuRedraw=true; 1033 curFile -= 9; 1034 } else if (curFile!=0) { 1035 menuRedraw=true; 1036 curFile--; 1037 } 1038 } 1039 else if ( (bClick & MASK_JOY2_DOWN) || (bClick & MASK_JOY1_DOWN) ) { 1040 if ((curFile<(nbFiles-1)) && (nbFiles)) { 1041 curFile++; 1042 menuRedraw=true; 1043 } 1044 } 1045 else if ( (bClick & MASK_JOY2_LEFT) || (bClick & MASK_JOY1_LEFT) ) { 1046 if ((curFile<(nbFiles-9)) && (nbFiles)) { 1047 curFile += 9; 1048 menuRedraw=true; 1049 } 1050 else if ((curFile<(nbFiles-1)) && (nbFiles)) { 1051 curFile++; 1052 menuRedraw=true; 1053 } 1054 } 1055 1056 if (menuRedraw && nbFiles) { 1057 int fileIndex = 0; 1058 tft.drawRectNoDma(MENU_FILE_XOFFSET,MENU_FILE_YOFFSET, MENU_FILE_W, MENU_FILE_H, MENU_FILE_BGCOLOR); 1059 // if (curFile <= (MAX_MENULINES/2-1)) topFile=0; 1060 // else topFile=curFile-(MAX_MENULINES/2); 1061 if (curFile <= (MAX_MENULINES-1)) topFile=0; 1062 else topFile=curFile-(MAX_MENULINES/2); 1063 1064 //Serial.print("curfile: "); 1065 //Serial.println(curFile); 1066 //Serial.print("topFile: "); 1067 //Serial.println(topFile); 1068 1069 int i=0; 1070 while (i<MAX_MENULINES) { 1071 if (fileIndex>=nbFiles) { 1072 // no more files 1073 break; 1074 } 1075 char * filename = &files[fileIndex][0]; 1076 if (fileIndex >= topFile) { 1077 if ((i+topFile) < nbFiles ) { 1078 if ((i+topFile)==curFile) { 1079 tft.drawTextNoDma(MENU_FILE_XOFFSET,i*TEXT_HEIGHT+MENU_FILE_YOFFSET, filename, RGBVAL16(0xff,0xff,0x00), RGBVAL16(0xff,0x00,0x00), true); 1080 strcpy(selected_filename,filename); 1081 } 1082 else { 1083 tft.drawTextNoDma(MENU_FILE_XOFFSET,i*TEXT_HEIGHT+MENU_FILE_YOFFSET, filename, RGBVAL16(0xff,0xff,0xff), MENU_FILE_BGCOLOR, true); 1084 } 1085 } 1086 i++; 1087 } 1088 fileIndex++; 1089 } 1090 1091 1092 // tft.drawTextNoDma(48,MENU_JOYS_YOFFSET+8, (emu_SwapJoysticks(1)?(char*)"SWAP=1":(char*)"SWAP=0"), RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), false); 1093 tft.drawTextNoDma(48,MENU_JOYS_YOFFSET+8, "FLOPPY2:", RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), false); 1094 tft.drawRectNoDma(120,MENU_JOYS_YOFFSET+8, MENU_FILE_W, 8, RGBVAL16(0x00,0x00,0x00)); 1095 tft.drawTextNoDma(120,MENU_JOYS_YOFFSET+8, second_selected_filename, RGBVAL16(0xff,0xff,0xff), RGBVAL16(0x00,0x00,0x00), false); 1096 menuRedraw=false; 1097 } 1098 1099 return (action); 1100 } 1101 1102 bool menuActive(void) 1103 { 1104 return (menuOn); 1105 } 1106 1107 void toggleMenu(bool on) { 1108 if (on) { 1109 menuOn=true; 1110 backgroundMenu(); 1111 } else { 1112 menuOn = false; 1113 } 1114 } 1115 1116 char * menuSelection(void) 1117 { 1118 return (selection); 1119 } 1120 1121 char * menuSecondSelection(void) 1122 { 1123 return (second_selection); 1124 } 1125 1126 1127 /******************************** 1128 * OSKB handling 1129 ********************************/ 1130 static bool oskbOn = false; 1131 static int cxpos = 0; 1132 static int cypos = 0; 1133 static uint16_t oskbBLastState = 0; 1134 #define OSKBHEIGHT 4 1135 #define OSKBXOFF 16 1136 #define OSKBYOFF 0 1137 1138 static void lineOSKB(int xoff, bool bottom, char * str, int row) 1139 { 1140 char c[4] = {' ',0,' ',0}; 1141 const char * cpt = str; 1142 int i=0; 1143 int fb_width,fb_height; 1144 tft.get_frame_buffer_size(&fb_width, &fb_height); 1145 int ypos = (bottom?(fb_height-2*8):0); 1146 int line = row + (bottom?2:0); 1147 while ((c[1] = *cpt++)) 1148 { 1149 uint16_t bg; 1150 if (row&1) bg = (i&1)?RGBVAL16(0xff,0xff,0xff):RGBVAL16(0xe0,0xe0,0xe0); 1151 else bg = (i&1)?RGBVAL16(0xe0,0xe0,0xe0):RGBVAL16(0xff,0xff,0xff); 1152 if ( (cxpos == i) && (cypos == line) ) bg = RGBVAL16(0x00,0xff,0xff); 1153 tft.drawTextNoDma(OSKBXOFF+xoff+24*i,OSKBYOFF+ypos+8*row , &c[0], RGBVAL16(0x00,0x00,0x00), bg, false); 1154 i++; 1155 } 1156 } 1157 1158 static int linelenOSKB() { 1159 if (cypos == 0) return strlen(keylables_map0_0); 1160 else if (cypos == 1) return strlen(keylables_map0_1); 1161 else if (cypos == 2) return strlen(keylables_map0_2); 1162 else return strlen(keylables_map0_3); 1163 } 1164 1165 static void drawOSKB() { 1166 if (key_extmode) { 1167 if (key_fn) { 1168 lineOSKB(16,false, keylables_map5_0, 0); 1169 lineOSKB(8, false, keylables_map5_1, 1); 1170 lineOSKB(0, true, keylables_map5_2, 0); 1171 lineOSKB(96,true, keylables_map5_3, 1); 1172 } 1173 else if (key_sh) { 1174 lineOSKB(16,false, keylables_map4_0, 0); 1175 lineOSKB(8, false, keylables_map4_1, 1); 1176 lineOSKB(0, true, keylables_map4_2, 0); 1177 lineOSKB(96,true, keylables_map4_3, 1); 1178 } 1179 else { 1180 lineOSKB(16,false, keylables_map3_0, 0); 1181 lineOSKB(8, false, keylables_map3_1, 1); 1182 lineOSKB(0, true, keylables_map3_2, 0); 1183 lineOSKB(96,true, keylables_map3_3, 1); 1184 } 1185 } 1186 else { 1187 if (key_fn) { 1188 lineOSKB(16,false, keylables_map2_0, 0); 1189 lineOSKB(8, false, keylables_map2_1, 1); 1190 lineOSKB(0, true, keylables_map2_2, 0); 1191 lineOSKB(96,true, keylables_map2_3, 1); 1192 } 1193 else if (key_sh) { 1194 lineOSKB(16,false, keylables_map1_0, 0); 1195 lineOSKB(8, false, keylables_map1_1, 1); 1196 lineOSKB(0, true, keylables_map1_2, 0); 1197 lineOSKB(96,true, keylables_map1_3, 1); 1198 } 1199 else { 1200 lineOSKB(16,false, keylables_map0_0, 0); 1201 lineOSKB(8, false, keylables_map0_1, 1); 1202 lineOSKB(0, true, keylables_map0_2, 0); 1203 lineOSKB(96,true, keylables_map0_3, 1); 1204 } 1205 } 1206 } 1207 1208 int handleOSKB(void) { 1209 int retval = 0; 1210 if (oskbOn) { 1211 uint16_t bClick = bLastState & ~oskbBLastState; 1212 oskbBLastState = bLastState; 1213 bool updated = true; 1214 if (bClick & MASK_KEY_USER1) 1215 { 1216 } 1217 else if (bClick & MASK_JOY2_RIGHT) 1218 { 1219 cxpos++; 1220 if (cxpos >= linelenOSKB()) cxpos = 0; 1221 } 1222 else if (bClick & MASK_JOY2_LEFT) 1223 { 1224 cxpos--; 1225 if (cxpos < 0) cxpos = linelenOSKB()-1; 1226 } 1227 else if (bClick & MASK_JOY2_DOWN) 1228 { 1229 cypos++; 1230 if (cypos >= OSKBHEIGHT) cypos = 0; 1231 if (cxpos >= linelenOSKB()) cxpos = linelenOSKB()-1; 1232 } 1233 else if (bClick & MASK_JOY2_UP) 1234 { 1235 cypos--; 1236 if (cypos < 0) cypos = OSKBHEIGHT-1; 1237 if (cxpos >= linelenOSKB()) cxpos = linelenOSKB()-1; 1238 } 1239 else if (oskbBLastState & MASK_JOY2_BTN) 1240 { 1241 //if (retval) { toggleOSKB(false); updated=false; }; 1242 } 1243 else { 1244 updated=false; 1245 } 1246 /*if (updated)*/ drawOSKB(); 1247 } 1248 return retval; 1249 } 1250 1251 void toggleOSKB(bool forceon) { 1252 if (forceon) { 1253 oskbOn = true; 1254 drawOSKB(); 1255 } 1256 else { 1257 if (oskbOn) { 1258 oskbOn = false; 1259 } 1260 else { 1261 oskbOn = true; 1262 drawOSKB(); 1263 } 1264 } 1265 } 1266 1267 1268 1269 /******************************** 1270 * File IO 1271 ********************************/ 1272 static File file_handlers[NB_FILE_HANDLER]; 1273 1274 static void FileHandlersInit(void) { 1275 for (int i=0; i<NB_FILE_HANDLER;i++) { 1276 file_handlers[i]=file; 1277 } 1278 } 1279 1280 static int getFreeFileHandler(void) { 1281 for (int i=0; i<NB_FILE_HANDLER; i++) { 1282 if (!file_handlers[i] != file) return i; 1283 } 1284 emu_printf("No free file handler"); 1285 return -1; 1286 } 1287 1288 static File getFileHandler(int handler) { 1289 return (file_handlers[handler-1]); 1290 } 1291 1292 //#define HCFH 1 1293 1294 int emu_FileOpen(const char * filepath, const char * mode) 1295 { 1296 // emu_printf("FileOpen..."); 1297 // emu_printf(filepath); 1298 #ifdef HCFH 1299 int retval = 0; 1300 if ((file = SD.open(filepath, O_READ))) { 1301 retval = 1; 1302 } 1303 else { 1304 emu_printf("FileOpen failed"); 1305 } 1306 return (retval); 1307 #else 1308 int retval = 0; 1309 int handler = getFreeFileHandler(); 1310 if (handler >= 0) { 1311 if ((file_handlers[handler] = SD.open(filepath, O_READ))) { 1312 // emu_printi(handler+1); 1313 retval = handler+1; 1314 } 1315 else { 1316 file_handlers[handler] = file; 1317 emu_printf("FileOpen failed"); 1318 } 1319 } 1320 return (retval); 1321 #endif 1322 } 1323 1324 int emu_FileRead(void * buf, int size, int handler) 1325 { 1326 // emu_printf("FileRead"); 1327 // emu_printi(handler); 1328 #ifdef HCFH 1329 return (file.read(buf, size)); 1330 #else 1331 return (getFileHandler(handler).read(buf, size)); 1332 #endif 1333 } 1334 1335 int emu_FileGetc(int handler) { 1336 // emu_printf("FileGetc"); 1337 // emu_printi(handler); 1338 #ifdef HCFH 1339 unsigned char c; 1340 int retval = file.read(&c, 1); 1341 if (retval != 1) { 1342 emu_printf("emu_FileGetc failed"); 1343 } 1344 return (int)c; 1345 #else 1346 unsigned char c; 1347 int retval = getFileHandler(handler).read(&c, 1); 1348 if (retval != 1) { 1349 emu_printf("emu_FileGetc failed"); 1350 } 1351 return (int)c; 1352 #endif 1353 } 1354 1355 int emu_FileSeek(int handler, int seek, int origin) 1356 { 1357 // emu_printf("FileSeek"); 1358 // emu_printi(handler); 1359 // emu_printi(seek); 1360 #ifdef HCFH 1361 file.seek(seek); 1362 return (seek); 1363 #else 1364 getFileHandler(handler).seek(seek); 1365 return (seek); 1366 #endif 1367 } 1368 1369 int emu_FileTell(int handler) { 1370 // emu_printf("FileTell"); 1371 // emu_printi(handler); 1372 #ifdef HCFH 1373 return (50); 1374 #else 1375 File file = getFileHandler(handler); 1376 return (emu_FileSize((char*)file.name())); 1377 #endif 1378 } 1379 1380 1381 void emu_FileClose(int handler) 1382 { 1383 // emu_printf("FileClose"); 1384 // emu_printi(handler); 1385 #ifdef HCFH 1386 file.close(); 1387 #else 1388 getFileHandler(handler).close(); 1389 file_handlers[handler-1] = file; 1390 #endif 1391 } 1392 1393 1394 static File lofile; 1395 1396 unsigned int emu_FileSize(const char * filepath) 1397 { 1398 unsigned int filesize=0; 1399 emu_printf(filepath); 1400 if ((lofile = SD.open(filepath, O_READ))) 1401 { 1402 emu_printf("filesize is..."); 1403 filesize = lofile.size(); 1404 emu_printf(filesize); 1405 lofile.close(); 1406 } 1407 return(filesize); 1408 } 1409 1410 unsigned int emu_LoadFile(const char * filepath, void * buf, int size) 1411 { 1412 unsigned int filesize = 0; 1413 emu_printf("LoadFile..."); 1414 emu_printf(filepath); 1415 if ((lofile = SD.open(filepath, O_READ))) 1416 { 1417 filesize = lofile.size(); 1418 emu_printf(filesize); 1419 if ((unsigned int)size >= filesize) 1420 { 1421 if (lofile.read(buf, filesize) != filesize) 1422 { 1423 emu_printf("File read failed"); 1424 } 1425 } 1426 lofile.close(); 1427 } 1428 return(filesize); 1429 } 1430 1431 unsigned int emu_LoadFileSeek(const char * filepath, void * buf, int size, int seek) 1432 { 1433 unsigned int filesize = 0; 1434 emu_printf("LoadFileSeek..."); 1435 emu_printf(filepath); 1436 if ((lofile = SD.open(filepath, O_READ))) 1437 { 1438 lofile.seek(seek); 1439 emu_printf(size); 1440 if (lofile.read(buf, size) != (unsigned int)size) { 1441 emu_printf("File read failed"); 1442 } 1443 lofile.close(); 1444 } 1445 return(filesize); 1446 } 1447 1448 static bool emu_writeConfig(void) 1449 { 1450 bool retval = false; 1451 if ((lofile = SD.open(ROMSDIR "/" AUTORUN_FILENAME, O_CREAT | O_WRITE))) 1452 { 1453 if (lofile.write(selection, strlen(selection)) != strlen(selection)) { 1454 emu_printf("Config write failed"); 1455 } 1456 else { 1457 retval = true; 1458 } 1459 lofile.close(); 1460 } 1461 return retval; 1462 } 1463 1464 static bool emu_readConfig(void) 1465 { 1466 bool retval = false; 1467 1468 if ((lofile = SD.open(ROMSDIR "/" AUTORUN_FILENAME, O_READ))) 1469 { 1470 unsigned int filesize = lofile.size(); 1471 unsigned int sizeread = lofile.read(selection, filesize); 1472 if (sizeread != filesize) { 1473 emu_printf("Config read failed"); 1474 } 1475 else { 1476 if (sizeread == filesize) 1477 { 1478 selection[filesize]=0; 1479 retval = true; 1480 } 1481 } 1482 lofile.close(); 1483 } 1484 return retval; 1485 } 1486 1487 static bool emu_eraseConfig(void) 1488 { 1489 SD.remove (ROMSDIR "/" AUTORUN_FILENAME); 1490 } 1491 1492 /******************************** 1493 * File IO compatibility 1494 ********************************/ 1495 #ifdef HAS_EXTFF 1496 1497 #include "ff.h" 1498 1499 typedef struct { 1500 File f; 1501 int offset; 1502 int size; 1503 int used; 1504 } FileDesc; 1505 1506 typedef int * FIL; 1507 1508 1509 1510 #define NO_MMAP_HANDLES 32 1511 1512 static FileDesc fds[NO_MMAP_HANDLES]; 1513 static int nextHandle=0; 1514 1515 static void freeHandle(int h) { 1516 fds[h].used = 0; 1517 } 1518 1519 1520 static int getFreeHandle() { 1521 int n=NO_MMAP_HANDLES; 1522 while (fds[nextHandle].used!=0 && n!=0) { 1523 nextHandle++; 1524 if (nextHandle==NO_MMAP_HANDLES) nextHandle=0; 1525 n-1; 1526 } 1527 if (n==0) { 1528 emu_printf("getFreeHandle error"); 1529 return; 1530 } 1531 1532 int r=nextHandle; 1533 fds[r].used = 1; 1534 nextHandle++; 1535 if (nextHandle==NO_MMAP_HANDLES) nextHandle=0; 1536 1537 return r; 1538 } 1539 1540 FRESULT f_open (FIL* fp, const char * path, unsigned char mode) 1541 { 1542 emu_printf("fopen"); 1543 emu_printf((char*)path); 1544 int i=getFreeHandle(); 1545 emu_printf(i); 1546 fds[i].f = SD.open(path, O_READ); 1547 *fp = i; 1548 if (fds[i].f) { 1549 fds[i].size = fds[i].f.size(); 1550 emu_printi(fds[i].size); 1551 return(FR_OK); 1552 } 1553 emu_printf("error"); 1554 freeHandle(fds[i].f); 1555 return(FR_NO_FILE); 1556 } 1557 1558 FRESULT f_close (FIL* fp) 1559 { 1560 int i = *fp; 1561 emu_printf("fclose"); 1562 emu_printi(i); 1563 fds[i].f.close(); 1564 freeHandle(i); 1565 return(FR_OK); 1566 } 1567 1568 FRESULT f_read (FIL* fp, void* buff, unsigned int btr, unsigned int * br) 1569 { 1570 int i = *fp; 1571 1572 if (btr < 64738) { 1573 int nr = fds[i].f.read(buff, btr); 1574 //emu_printf("fread"); 1575 //emu_printi(btr); 1576 //emu_printi(nr); 1577 *br = nr; 1578 if (nr <= 0) 1579 return(FR_DISK_ERR); 1580 else 1581 return(FR_OK); 1582 } 1583 1584 unsigned char buffer[256]; 1585 1586 int remaining = btr; 1587 int byteread = 0; 1588 int retval=0; 1589 1590 while (remaining>0) { 1591 if (remaining < 256) 1592 retval = fds[i].f.read(buffer, remaining); 1593 else 1594 retval = fds[i].f.read(buffer, 256); 1595 if (retval>0) { 1596 memcpy(buff,buffer,retval); 1597 buff += retval; 1598 byteread += retval; 1599 remaining -= retval; 1600 } 1601 else { 1602 break; 1603 } 1604 } 1605 *br = byteread; 1606 //emu_printi(byteread); 1607 if (byteread <= 0) 1608 return(FR_DISK_ERR); 1609 else 1610 return(FR_OK); 1611 } 1612 1613 FRESULT f_readn (FIL* fp, void* buff, unsigned int btr, unsigned int * br) 1614 { 1615 return(f_read (fp, buff, btr, br)); 1616 } 1617 1618 FRESULT f_write (FIL* fp, const void* buff, unsigned int btw, unsigned int * bw) 1619 { 1620 return(FR_OK); 1621 } 1622 FRESULT f_writen (FIL* fp, const void* buff, unsigned int btw, unsigned int * bw) 1623 { 1624 return(FR_OK); 1625 } 1626 FRESULT f_lseek (FIL* fp, unsigned long ofs) 1627 { 1628 int i = *fp; 1629 //emu_printf("fseek"); 1630 //emu_printi(ofs); 1631 fds[i].f.seek(ofs); 1632 return(FR_OK); 1633 } 1634 1635 1636 FRESULT f_unlink (const char * path) 1637 { 1638 return(FR_OK); 1639 } 1640 FRESULT f_rename (const char * path_old, const char * path_new) 1641 { 1642 return(FR_OK); 1643 } 1644 FRESULT f_stat (const char * path, FILINFO* fno) 1645 { 1646 return(FR_OK); 1647 } 1648 1649 unsigned long f_tell (FIL * fp) 1650 { 1651 int i = *fp; 1652 emu_printf("ftell"); 1653 return(fds[i].size); 1654 //return(fds[i].f.ftell()); 1655 } 1656 1657 unsigned long f_size (FIL * fp) 1658 { 1659 int i = *fp; 1660 emu_printf("fsize"); 1661 emu_printi(fds[i].size); 1662 return(fds[i].size); 1663 } 1664 1665 FRESULT f_mkdir (const char* path) 1666 { 1667 return(FR_OK); 1668 } 1669 #endif 1670 1671 1672 /******************************** 1673 * Initialization 1674 ********************************/ 1675 void emu_init(void) 1676 { 1677 Serial.begin(115200); 1678 1679 #ifdef HAS_USBKEY 1680 myusb.begin(); 1681 keyboard1.attachPress(OnPress); 1682 keyboard1.attachRelease(OnRelease); 1683 #endif 1684 1685 while (!SD.begin(SD_CS)) 1686 { 1687 Serial.println("SD begin failed, retrying..."); 1688 delay(1000); 1689 } 1690 strcpy(selection,ROMSDIR); 1691 1692 FileHandlersInit(); 1693 1694 nbFiles = readNbFiles(); 1695 1696 Serial.print("SD initialized, files found: "); 1697 Serial.println(nbFiles); 1698 1699 emu_InitJoysticks(); 1700 #ifdef SWAP_JOYSTICK 1701 joySwapped = true; 1702 #else 1703 joySwapped = false; 1704 #endif 1705 1706 #ifdef TEECOMPUTER 1707 #ifndef HAS_T4_VGA 1708 tft.flipscreen(true); 1709 #endif 1710 #endif 1711 int keypressed = emu_ReadKeys(); 1712 if (keypressed & MASK_JOY2_DOWN) { 1713 tft.fillScreenNoDma( RGBVAL16(0xff,0x00,0x00) ); 1714 tft.drawTextNoDma(64,48, (char*)" AUTURUN file erased", RGBVAL16(0xff,0xff,0x00), RGBVAL16(0xff,0x00,0x00), true); 1715 emu_eraseConfig(); 1716 delay(1000); 1717 } 1718 else { 1719 if (emu_readConfig()) { 1720 autorun = true; 1721 } 1722 } 1723 1724 toggleMenu(true); 1725 } 1726 1727 1728 void emu_start(void) 1729 { 1730 usbnavpad = 0; 1731 }