ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/Frodo4/Src/IEC.cpp
(Generate patch)

Comparing Frodo4/Src/IEC.cpp (file contents):
Revision 1.2 by cebix, 2003-07-01T17:51:17Z vs.
Revision 1.3 by cebix, 2004-01-11T00:09:51Z

# Line 367 | Line 367 | uint8 IEC::open_out(uint8 byte, bool eoi
367                  *name_ptr = 0;                          // End string
368                  listener->LED = DRVLED_ON;      // Turn on drive LED
369                  UpdateLEDs();
370 <                return listener->Open(sec_addr, name_buf);
370 >                return listener->Open(sec_addr, name_buf, name_len);
371          }
372  
373          return ST_OK;
# Line 412 | Line 412 | Drive::Drive(IEC *iec)
412   */
413  
414   // 1541 error messages
415 < char *Errors_1541[] = {
416 <        "00, OK,00,00\r",
417 <        "25,WRITE ERROR,00,00\r",
418 <        "26,WRITE PROTECT ON,00,00\r",
419 <        "30,SYNTAX ERROR,00,00\r",
420 <        "33,SYNTAX ERROR,00,00\r",
421 <        "60,WRITE FILE OPEN,00,00\r",
422 <        "61,FILE NOT OPEN,00,00\r",
423 <        "62,FILE NOT FOUND,00,00\r",
424 <        "67,ILLEGAL TRACK OR SECTOR,00,00\r",
425 <        "70,NO CHANNEL,00,00\r",
426 <        "73,CBM DOS V2.6 1541,00,00\r",
427 <        "74,DRIVE NOT READY,00,00\r"
415 > static const char *Errors_1541[] = {
416 >        "00, OK,%02d,%02d\x0d",
417 >        "01, FILES SCRATCHED,%02d,%02d\x0d",
418 >        "03, UNIMPLEMENTED,%02d,%02d\x0d",
419 >        "20, READ ERROR,%02d,%02d\x0d",
420 >        "21, READ ERROR,%02d,%02d\x0d",
421 >        "22, READ ERROR,%02d,%02d\x0d",
422 >        "23, READ ERROR,%02d,%02d\x0d",
423 >        "24, READ ERROR,%02d,%02d\x0d",
424 >        "25, WRITE ERROR,%02d,%02d\x0d",
425 >        "26, WRITE PROTECT ON,%02d,%02d\x0d",
426 >        "27, READ ERROR,%02d,%02d\x0d",
427 >        "28, WRITE ERROR,%02d,%02d\x0d",
428 >        "29, DISK ID MISMATCH,%02d,%02d\x0d",
429 >        "30, SYNTAX ERROR,%02d,%02d\x0d",
430 >        "31, SYNTAX ERROR,%02d,%02d\x0d",
431 >        "32, SYNTAX ERROR,%02d,%02d\x0d",
432 >        "33, SYNTAX ERROR,%02d,%02d\x0d",
433 >        "34, SYNTAX ERROR,%02d,%02d\x0d",
434 >        "60, WRITE FILE OPEN,%02d,%02d\x0d",
435 >        "61, FILE NOT OPEN,%02d,%02d\x0d",
436 >        "62, FILE NOT FOUND,%02d,%02d\x0d",
437 >        "63, FILE EXISTS,%02d,%02d\x0d",
438 >        "64, FILE TYPE MISMATCH,%02d,%02d\x0d",
439 >        "65, NO BLOCK,%02d,%02d\x0d",
440 >        "66, ILLEGAL TRACK OR SECTOR,%02d,%02d\x0d",
441 >        "70, NO CHANNEL,%02d,%02d\x0d",
442 >        "71, DIR ERROR,%02d,%02d\x0d",
443 >        "72, DISK FULL,%02d,%02d\x0d",
444 >        "73, CBM DOS V2.6 1541,%02d,%02d\x0d",
445 >        "74, DRIVE NOT READY,%02d,%02d\x0d"
446   };
447  
448 < void Drive::set_error(int error)
448 > void Drive::set_error(int error, int track, int sector)
449   {
450 <        error_ptr = Errors_1541[error];
451 <        error_len = strlen(error_ptr);
450 >        // Write error message to buffer
451 >        sprintf(error_buf, Errors_1541[error], track, sector);
452 >        error_ptr = error_buf;
453 >        error_len = strlen(error_buf);
454  
455          // Set drive condition
456 <        if (error != ERR_OK)
456 >        if (error != ERR_OK && error != ERR_SCRATCHED)
457                  if (error == ERR_STARTUP)
458                          LED = DRVLED_OFF;
459                  else
# Line 442 | Line 462 | void Drive::set_error(int error)
462                  LED = DRVLED_OFF;
463          the_iec->UpdateLEDs();
464   }
465 +
466 +
467 + /*
468 + *  Parse file name, determine access mode and file type
469 + */
470 +
471 + void Drive::parse_file_name(const uint8 *src, int src_len, uint8 *dest, int &dest_len, int &mode, int &type, int &rec_len, bool convert_charset)
472 + {
473 +        // If the string contains a ':', the file name starts after that
474 +        const uint8 *p = (const uint8 *)memchr(src, ':', src_len);
475 +        if (p) {
476 +                p++;
477 +                src_len -= p - src;
478 +        } else
479 +                p = src;
480 +
481 +        // Transfer file name upto ','
482 +        dest_len = 0;
483 +        uint8 *q = dest;
484 +        while (*p != ',' && src_len-- > 0) {
485 +                if (convert_charset)
486 +                        *q++ = petscii2ascii(*p++);
487 +                else
488 +                        *q++ = *p++;
489 +                dest_len++;
490 +        }
491 +        *q++ = 0;
492 +
493 +        // Strip trailing CRs
494 +        while (dest_len > 0 && dest[dest_len - 1] == 0x0d)
495 +                dest[--dest_len] = 0;
496 +
497 +        // Look for mode and type parameters separated by ','
498 +        p++; src_len--;
499 +        while (src_len > 0) {
500 +                switch (*p) {
501 +                        case 'D':
502 +                                type = FTYPE_DEL;
503 +                                break;
504 +                        case 'S':
505 +                                type = FTYPE_SEQ;
506 +                                break;
507 +                        case 'P':
508 +                                type = FTYPE_PRG;
509 +                                break;
510 +                        case 'U':
511 +                                type = FTYPE_USR;
512 +                                break;
513 +                        case 'L':
514 +                                type = FTYPE_REL;
515 +                                while (*p != ',' && src_len-- > 0) p++;
516 +                                p++; src_len--;
517 +                                rec_len = *p++; src_len--;
518 +                                if (src_len < 0)
519 +                                        rec_len = 0;
520 +                                break;
521 +                        case 'R':
522 +                                mode = FMODE_READ;
523 +                                break;
524 +                        case 'W':
525 +                                mode = FMODE_WRITE;
526 +                                break;
527 +                        case 'A':
528 +                                mode = FMODE_APPEND;
529 +                                break;
530 +                        case 'M':
531 +                                mode = FMODE_M;
532 +                                break;
533 +                }
534 +
535 +                // Skip to ','
536 +                while (*p != ',' && src_len-- > 0) p++;
537 +                p++; src_len--;
538 +        }
539 + }
540 +
541 +
542 + /*
543 + *  Execute DOS command (parse command and call appropriate routine)
544 + */
545 +
546 + static void parse_block_cmd_args(const uint8 *p, int &arg1, int &arg2, int &arg3, int &arg4)
547 + {
548 +        arg1 = arg2 = arg3 = arg4 = 0;
549 +
550 +        while (*p == ' ' || *p == 0x1d || *p == ',') p++;
551 +        while (*p >= '0' && *p < '@')
552 +                arg1 = arg1 * 10 + (*p++ & 0x0f);
553 +
554 +        while (*p == ' ' || *p == 0x1d || *p == ',') p++;
555 +        while (*p >= '0' && *p < '@')
556 +                arg2 = arg2 * 10 + (*p++ & 0x0f);
557 +
558 +        while (*p == ' ' || *p == 0x1d || *p == ',') p++;
559 +        while (*p >= '0' && *p < '@')
560 +                arg3 = arg3 * 10 + (*p++ & 0x0f);
561 +
562 +        while (*p == ' ' || *p == 0x1d || *p == ',') p++;
563 +        while (*p >= '0' && *p < '@')
564 +                arg4 = arg4 * 10 + (*p++ & 0x0f);
565 + }
566 +
567 + void Drive::execute_cmd(const uint8 *cmd, int cmd_len)
568 + {
569 +        // Strip trailing CRs
570 +        while (cmd_len > 0 && cmd[cmd_len - 1] == 0x0d)
571 +                cmd_len--;
572 +
573 +        // Find token delimiters
574 +        const uint8 *colon = (const uint8 *)memchr(cmd, ':', cmd_len);
575 +        const uint8 *equal = colon ? (const uint8 *)memchr(colon, '=', cmd_len - (colon - cmd)) : NULL;
576 +        const uint8 *comma = (const uint8 *)memchr(cmd, ',', cmd_len);
577 +        const uint8 *minus = (const uint8 *)memchr(cmd, '-', cmd_len);
578 +
579 +        // Parse command name
580 +        set_error(ERR_OK);
581 +        switch (cmd[0]) {
582 +                case 'B':       // Block/buffer
583 +                        if (!minus)
584 +                                set_error(ERR_SYNTAX31);
585 +                        else {
586 +                                // Parse arguments (up to 4 decimal numbers separated by
587 +                                // space, cursor right or comma)
588 +                                const uint8 *p = colon ? colon + 1 : cmd + 3;
589 +                                int arg1, arg2, arg3, arg4;
590 +                                parse_block_cmd_args(p, arg1, arg2, arg3, arg4);
591 +
592 +                                // Switch on command
593 +                                switch (minus[1]) {
594 +                                        case 'R':
595 +                                                block_read_cmd(arg1, arg3, arg4);
596 +                                                break;
597 +                                        case 'W':
598 +                                                block_write_cmd(arg1, arg3, arg4);
599 +                                                break;
600 +                                        case 'E':
601 +                                                block_execute_cmd(arg1, arg3, arg4);
602 +                                                break;
603 +                                        case 'A':
604 +                                                block_allocate_cmd(arg2, arg3);
605 +                                                break;
606 +                                        case 'F':
607 +                                                block_free_cmd(arg2, arg3);
608 +                                                break;
609 +                                        case 'P':
610 +                                                buffer_pointer_cmd(arg1, arg2);
611 +                                                break;
612 +                                        default:
613 +                                                set_error(ERR_SYNTAX31);
614 +                                                break;
615 +                                }
616 +                        }
617 +                        break;
618 +
619 +                case 'M':       // Memory
620 +                        if (cmd[1] != '-')
621 +                                set_error(ERR_SYNTAX31);
622 +                        else {
623 +                                // Read parameters
624 +                                uint16 adr = uint8(cmd[3]) | (uint8(cmd[4]) << 8);
625 +                                uint8 len = uint8(cmd[5]);
626 +
627 +                                // Switch on command
628 +                                switch (cmd[2]) {
629 +                                        case 'R':
630 +                                                mem_read_cmd(adr, (cmd_len < 6) ? 1 : len);
631 +                                                break;
632 +                                        case 'W':
633 +                                                mem_write_cmd(adr, len, (uint8 *)cmd + 6);
634 +                                                break;
635 +                                        case 'E':
636 +                                                mem_execute_cmd(adr);
637 +                                                break;
638 +                                        default:
639 +                                                set_error(ERR_SYNTAX31);
640 +                                                break;
641 +                                }
642 +                        }
643 +                        break;
644 +
645 +                case 'C':       // Copy
646 +                        if (!colon)
647 +                                set_error(ERR_SYNTAX31);
648 +                        else if (!equal || memchr(cmd, '*', cmd_len) || memchr(cmd, '?', cmd_len) || (comma && comma < equal))
649 +                                set_error(ERR_SYNTAX30);
650 +                        else
651 +                                copy_cmd(colon + 1, equal - colon - 1, equal + 1, cmd_len - (equal + 1 - cmd));
652 +                        break;
653 +
654 +                case 'R':       // Rename
655 +                        if (!colon)
656 +                                set_error(ERR_SYNTAX34);
657 +                        else if (!equal || comma || memchr(cmd, '*', cmd_len) || memchr(cmd, '?', cmd_len))
658 +                                set_error(ERR_SYNTAX30);
659 +                        else
660 +                                rename_cmd(colon + 1, equal - colon - 1, equal + 1, cmd_len - (equal + 1 - cmd));
661 +                        break;
662 +
663 +                case 'S':       // Scratch
664 +                        if (!colon)
665 +                                set_error(ERR_SYNTAX34);
666 +                        else
667 +                                scratch_cmd(colon + 1, cmd_len - (colon + 1 - cmd));
668 +                        break;
669 +
670 +                case 'P':       // Position
671 +                        position_cmd(cmd + 1, cmd_len - 1);
672 +                        break;
673 +
674 +                case 'I':       // Initialize
675 +                        initialize_cmd();
676 +                        break;
677 +
678 +                case 'N':       // New (format)
679 +                        if (!colon)
680 +                                set_error(ERR_SYNTAX34);
681 +                        else
682 +                                new_cmd(colon + 1, comma ? (comma - colon - 1) : cmd_len - (colon + 1 - cmd), comma);
683 +                        break;
684 +
685 +                case 'V':       // Validate
686 +                        validate_cmd();
687 +                        break;
688 +
689 +                case 'U':       // User
690 +                        if (cmd[1] == '0')
691 +                                break;
692 +                        switch (cmd[1] & 0x0f) {
693 +                                case 1: {       // U1/UA: Read block
694 +                                        const uint8 *p = colon ? colon + 1 : cmd + 2;
695 +                                        int arg1, arg2, arg3, arg4;
696 +                                        parse_block_cmd_args(p, arg1, arg2, arg3, arg4);
697 +                                        block_read_cmd(arg1, arg3, arg4, true);
698 +                                        break;
699 +                                }
700 +                                case 2: {       // U2/UB: Write block
701 +                                        const uint8 *p = colon ? colon + 1 : cmd + 2;
702 +                                        int arg1, arg2, arg3, arg4;
703 +                                        parse_block_cmd_args(p, arg1, arg2, arg3, arg4);
704 +                                        block_write_cmd(arg1, arg3, arg4, true);
705 +                                        break;
706 +                                }
707 +                                case 9:         // U9/UI: C64/VC20 mode switch
708 +                                        if (cmd[2] != '+' && cmd[2] != '-')
709 +                                                Reset();
710 +                                        break;
711 +                                case 10:        // U:/UJ: Reset
712 +                                        Reset();
713 +                                        break;
714 +                                default:
715 +                                        set_error(ERR_UNIMPLEMENTED);
716 +                                        break;
717 +                        }
718 +                        break;
719 +
720 +                default:
721 +                        set_error(ERR_SYNTAX31);
722 +                        break;
723 +        }
724 + }
725 +
726 + // BLOCK-READ:channel,0,track,sector
727 + void Drive::block_read_cmd(int channel, int track, int sector, bool user_cmd)
728 + {
729 +        set_error(ERR_UNIMPLEMENTED);
730 + }
731 +
732 + // BLOCK-WRITE:channel,0,track,sector
733 + void Drive::block_write_cmd(int channel, int track, int sector, bool user_cmd)
734 + {
735 +        set_error(ERR_UNIMPLEMENTED);
736 + }
737 +
738 + // BLOCK-EXECUTE:channel,0,track,sector
739 + void Drive::block_execute_cmd(int channel, int track, int sector)
740 + {
741 +        set_error(ERR_UNIMPLEMENTED);
742 + }
743 +
744 + // BLOCK-ALLOCATE:0,track,sector
745 + void Drive::block_allocate_cmd(int track, int sector)
746 + {
747 +        set_error(ERR_UNIMPLEMENTED);
748 + }
749 +
750 + // BLOCK-FREE:0,track,sector
751 + void Drive::block_free_cmd(int track, int sector)
752 + {
753 +        set_error(ERR_UNIMPLEMENTED);
754 + }
755 +
756 + // BUFFER-POINTER:channel,pos
757 + void Drive::buffer_pointer_cmd(int channel, int pos)
758 + {
759 +        set_error(ERR_UNIMPLEMENTED);
760 + }
761 +
762 + // M-R<adr low><adr high>[<number>]
763 + void Drive::mem_read_cmd(uint16 adr, uint8 len)
764 + {
765 +        unsupp_cmd();
766 +        error_ptr = error_buf;
767 +        error_buf[0] = 0;
768 +        error_len = 0;
769 +        set_error(ERR_OK);
770 + }
771 +
772 + // M-W<adr low><adr high><number><data...>
773 + void Drive::mem_write_cmd(uint16 adr, uint8 len, uint8 *p)
774 + {
775 +        set_error(ERR_UNIMPLEMENTED);
776 + }
777 +
778 + // M-E<adr low><adr high>
779 + void Drive::mem_execute_cmd(uint16 adr)
780 + {
781 +        set_error(ERR_UNIMPLEMENTED);
782 + }
783 +
784 + //   COPY:new=file1,file2,...
785 + //        ^   ^
786 + // new_file   old_files
787 + void Drive::copy_cmd(const uint8 *new_file, int new_file_len, const uint8 *old_files, int old_files_len)
788 + {
789 +        set_error(ERR_UNIMPLEMENTED);
790 + }
791 +
792 + // RENAME:new=old
793 + //        ^   ^
794 + // new_file   old_file
795 + void Drive::rename_cmd(const uint8 *new_file, int new_file_len, const uint8 *old_file, int old_file_len)
796 + {
797 +        set_error(ERR_UNIMPLEMENTED);
798 + }
799 +
800 + // SCRATCH:file1,file2,...
801 + //         ^
802 + //         files
803 + void Drive::scratch_cmd(const uint8 *files, int files_len)
804 + {
805 +        set_error(ERR_UNIMPLEMENTED);
806 + }
807 +
808 + // P<channel><record low><record high><byte>
809 + //  ^
810 + //  cmd
811 + void Drive::position_cmd(const uint8 *cmd, int cmd_len)
812 + {
813 +        set_error(ERR_UNIMPLEMENTED);
814 + }
815 +
816 + // INITIALIZE
817 + void Drive::initialize_cmd(void)
818 + {
819 +        set_error(ERR_UNIMPLEMENTED);
820 + }
821 +
822 + // NEW:name,id
823 + //     ^   ^
824 + //  name   comma (or NULL)
825 + void Drive::new_cmd(const uint8 *name, int name_len, const uint8 *comma)
826 + {
827 +        set_error(ERR_UNIMPLEMENTED);
828 + }
829 +
830 + // VALIDATE
831 + void Drive::validate_cmd(void)
832 + {
833 +        set_error(ERR_UNIMPLEMENTED);
834 + }
835 +
836 +
837 + /*
838 + *  Notice user of unsupported drive command
839 + */
840 +
841 + void Drive::unsupp_cmd(void)
842 + {
843 + }
844 +
845 +
846 + /*
847 + *  Convert PETSCII<->ASCII
848 + */
849 +
850 + char ascii2petscii(char c)
851 + {
852 +        if ((c >= 'A') && (c <= 'Z') || (c >= 'a') && (c <= 'z'))
853 +                return c ^ 0x20;
854 +        return c;
855 + }
856 +
857 + void ascii2petscii(char *dest, const char *src, int n)
858 + {
859 +        while (n-- && (*dest++ = ascii2petscii(*src++))) ;
860 + }
861 +
862 + char petscii2ascii(uint8 c)
863 + {
864 +        if ((c >= 'A') && (c <= 'Z') || (c >= 'a') && (c <= 'z'))
865 +                return c ^ 0x20;
866 +        if ((c >= 0xc1) && (c <= 0xda))
867 +                return c ^ 0x80;
868 +        return c;
869 + }
870 +
871 + void petscii2ascii(char *dest, const char *src, int n)
872 + {
873 +        while (n-- && (*dest++ = petscii2ascii(*src++))) ;
874 + }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines