trunk/src/mess/machine/psxcd.c
| r22512 | r22513 | |
| 125 | 125 | |
| 126 | 126 | void psxcd_device::device_reset() |
| 127 | 127 | { |
| 128 | next_read_event = -1; |
| 128 | 129 | stop_read(); |
| 129 | 130 | |
| 130 | 131 | for (int i = 0; i < MAX_PSXCD_TIMERS; i++) |
| r22512 | r22513 | |
| 149 | 150 | m_regs.imr = 0x1f; |
| 150 | 151 | sechead = 0; |
| 151 | 152 | sectail = 0; |
| 152 | | next_read_event = -1; |
| 153 | 153 | m_mute = false; |
| 154 | 154 | m_dmaload = false; |
| 155 | 155 | curpos.w = 0; |
| r22512 | r22513 | |
| 470 | 470 | start_read(); |
| 471 | 471 | } else |
| 472 | 472 | { |
| 473 | | send_result(intr_diskerror); |
| 473 | send_result(intr_diskerror, NULL, 0, 0x80); |
| 474 | 474 | } |
| 475 | 475 | } |
| 476 | 476 | |
| r22512 | r22513 | |
| 609 | 609 | decimal_to_bcd(loc.b[F]) // aframe |
| 610 | 610 | }; |
| 611 | 611 | |
| 612 | | verboselog(machine(), 1, "psxcd: getlocp [%02x %02x %02x %02x %02x %02x %02x %02x]\n", |
| 613 | | data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]); |
| 612 | verboselog(machine(), 1, "psxcd: getlocp [%02x %02x %02x %02x %02x %02x %02x %02x]\n", |
| 613 | data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]); |
| 614 | 614 | |
| 615 | 615 | send_result(intr_complete,data,8); |
| 616 | 616 | } |
| r22512 | r22513 | |
| 624 | 624 | { |
| 625 | 625 | unsigned char data[3]= |
| 626 | 626 | { |
| 627 | | status, |
| 628 | | decimal_to_bcd(1), |
| 629 | | decimal_to_bcd(cdrom_get_last_track(m_cdrom_handle)) |
| 627 | status, |
| 628 | decimal_to_bcd(1), |
| 629 | decimal_to_bcd(cdrom_get_last_track(m_cdrom_handle)) |
| 630 | 630 | }; |
| 631 | 631 | |
| 632 | 632 | send_result(intr_complete,data,3); |
| 633 | 633 | } |
| 634 | 634 | else |
| 635 | 635 | { |
| 636 | | status |= status_error; |
| 637 | | send_result(intr_diskerror); |
| 636 | send_result(intr_diskerror, NULL, 0, 0x80); |
| 638 | 637 | } |
| 639 | 638 | } |
| 640 | 639 | |
| r22512 | r22513 | |
| 663 | 662 | } |
| 664 | 663 | else |
| 665 | 664 | { |
| 666 | | status |= status_error; |
| 667 | | send_result(intr_diskerror); |
| 665 | send_result(intr_diskerror, NULL, 0, 0x80); |
| 668 | 666 | } |
| 669 | 667 | } |
| 670 | 668 | |
| r22512 | r22513 | |
| 688 | 686 | |
| 689 | 687 | void psxcd_device::cdcmd_test() |
| 690 | 688 | { |
| 691 | | verboselog(machine(), 1, "psxcd: test %08x\n",cmdbuf[0]); |
| 689 | verboselog(machine(), 1, "psxcd: test %02x\n", cmdbuf[0]); |
| 692 | 690 | |
| 693 | | static unsigned char data[4]= |
| 691 | switch(cmdbuf[0]) |
| 694 | 692 | { |
| 695 | | 0x95, |
| 696 | | 0x07, |
| 697 | | 0x06, |
| 698 | | 0xff |
| 699 | | }; |
| 693 | case 0x20: |
| 694 | static unsigned char data[4]= |
| 695 | { |
| 696 | 0x95, |
| 697 | 0x07, |
| 698 | 0x06, |
| 699 | 0xff |
| 700 | }; |
| 700 | 701 | |
| 701 | | send_result(intr_complete,data,4); |
| 702 | send_result(intr_complete,data,4); |
| 703 | break; |
| 704 | |
| 705 | default: |
| 706 | verboselog(machine(), 0, "psxcd: unimplemented test cmd %02x", cmdbuf[0]); |
| 707 | cmd_complete(prepare_result(intr_diskerror, NULL, 0, 0x10)); |
| 708 | break; |
| 709 | } |
| 702 | 710 | } |
| 703 | 711 | |
| 704 | 712 | void psxcd_device::cdcmd_id() |
| r22512 | r22513 | |
| 707 | 715 | |
| 708 | 716 | if (!open) |
| 709 | 717 | { |
| 710 | | static unsigned char gamedata[8] = { 0x00, 0x00, 0x00, 0x00, 'S', 'C', 'E', 'A' }; |
| 711 | | static unsigned char audiodata[8] = { 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // drops into the audio CD player. 08 80 goes to the menu. |
| 718 | UINT8 cdid[8]; |
| 719 | int irq; |
| 720 | memset(cdid, '\0', 8); |
| 712 | 721 | |
| 722 | send_result(intr_complete); |
| 713 | 723 | if(cdrom_get_track_type(m_cdrom_handle, 0) == CD_TRACK_AUDIO) |
| 714 | 724 | { |
| 715 | | audiodata[0] = status | status_invalid; |
| 716 | | send_result(intr_acknowledge,audiodata,8); |
| 725 | irq = intr_diskerror; |
| 726 | cdid[0] = status | status_invalid; |
| 727 | cdid[1] = 0x90; |
| 717 | 728 | } |
| 718 | 729 | else |
| 719 | 730 | { |
| 720 | | gamedata[0] = status; |
| 721 | | send_result(intr_acknowledge,gamedata,8); |
| 731 | irq = intr_acknowledge; |
| 732 | cdid[0] = status; |
| 733 | cdid[4] = 'S'; |
| 734 | cdid[5] = 'C'; |
| 735 | cdid[6] = 'E'; |
| 736 | cdid[7] = 'A'; |
| 722 | 737 | } |
| 723 | | } else |
| 738 | send_result(irq,cdid,8,default_irq_delay*3); |
| 739 | } |
| 740 | else |
| 724 | 741 | { |
| 725 | | status |= status_error; |
| 726 | | send_result(intr_diskerror); |
| 742 | send_result(intr_diskerror, NULL, 0, 0x80); |
| 727 | 743 | } |
| 728 | 744 | } |
| 729 | 745 | |
| r22512 | r22513 | |
| 739 | 755 | start_read(); |
| 740 | 756 | } else |
| 741 | 757 | { |
| 742 | | send_result(intr_diskerror); |
| 758 | send_result(intr_diskerror, NULL, 0, 0x80); |
| 743 | 759 | } |
| 744 | 760 | } |
| 745 | 761 | |
| r22512 | r22513 | |
| 753 | 769 | verboselog(machine(), 1, "psxcd: readtoc\n"); |
| 754 | 770 | |
| 755 | 771 | send_result(intr_complete); |
| 772 | send_result(intr_acknowledge, NULL, 0, default_irq_delay*3); // ? |
| 756 | 773 | } |
| 757 | 774 | |
| 758 | 775 | void psxcd_device::cdcmd_unknown12() |
| r22512 | r22513 | |
| 762 | 779 | if(cmdbuf[0] == 1) |
| 763 | 780 | send_result(intr_complete); |
| 764 | 781 | else |
| 765 | | { |
| 766 | | status |= status_error; |
| 767 | | send_result(intr_diskerror); |
| 768 | | } |
| 782 | send_result(intr_diskerror, NULL, 0, 0x40); |
| 769 | 783 | } |
| 770 | 784 | |
| 771 | 785 | void psxcd_device::cdcmd_illegal17() |
| r22512 | r22513 | |
| 786 | 800 | void psxcd_device::illegalcmd(UINT8 cmd) |
| 787 | 801 | { |
| 788 | 802 | verboselog(machine(), 0, "psxcd: unimplemented cd command %02x\n", cmd); |
| 789 | | command_result *res=global_alloc(command_result); |
| 790 | | res->res=intr_diskerror; |
| 791 | | res->data[0]=status | status_error; |
| 792 | | res->data[1]=0x40; //invalid command |
| 793 | | res->sz=2; |
| 794 | | cmd_complete(res); |
| 803 | |
| 804 | send_result(intr_diskerror, NULL, 0, 0x40); |
| 795 | 805 | } |
| 796 | 806 | |
| 797 | 807 | void psxcd_device::cmd_complete(command_result *res) |
| r22512 | r22513 | |
| 808 | 818 | else |
| 809 | 819 | { |
| 810 | 820 | res_queue = res; |
| 811 | | m_regs.ir = res_queue->res & m_regs.imr; // or should it not trigger a masked irq? |
| 812 | | if(m_regs.ir) |
| 821 | m_regs.ir = res_queue->res; |
| 822 | if(m_regs.ir & m_regs.imr) |
| 813 | 823 | m_irq_handler(1); |
| 814 | 824 | m_regs.sr |= 0x20; |
| 815 | 825 | } |
| 816 | 826 | res->next = NULL; |
| 817 | 827 | } |
| 818 | 828 | |
| 819 | | void psxcd_device::send_result(UINT8 res, UINT8 *data, int sz, int delay) |
| 829 | psxcd_device::command_result *psxcd_device::prepare_result(UINT8 res, UINT8 *data, int sz, UINT8 errcode) |
| 820 | 830 | { |
| 821 | 831 | command_result *cr=global_alloc(command_result); |
| 822 | 832 | |
| r22512 | r22513 | |
| 828 | 838 | cr->sz=sz; |
| 829 | 839 | } else |
| 830 | 840 | { |
| 831 | | cr->data[0]=status; |
| 832 | | cr->sz=1; |
| 841 | if((res == intr_diskerror) && errcode) |
| 842 | { |
| 843 | cr->data[0] = status | status_error; |
| 844 | cr->data[1] = errcode; |
| 845 | cr->sz = 2; |
| 846 | } |
| 847 | else |
| 848 | { |
| 849 | cr->data[0]=status; |
| 850 | cr->sz=1; |
| 851 | } |
| 833 | 852 | } |
| 834 | 853 | status &= ~status_error; |
| 835 | 854 | |
| 855 | return cr; |
| 856 | } |
| 857 | |
| 858 | void psxcd_device::send_result(UINT8 res, UINT8 *data, int sz, int delay, UINT8 errcode) |
| 859 | { |
| 836 | 860 | // Avoid returning results after sector read results - |
| 837 | 861 | // delay the sector read slightly if necessary |
| 838 | 862 | |
| r22512 | r22513 | |
| 843 | 867 | m_timers[next_read_event]->adjust(attotime::from_hz(hz), 0, attotime::never); |
| 844 | 868 | } |
| 845 | 869 | |
| 846 | | add_system_event(event_cmd_complete, delay, (void *)cr); |
| 870 | add_system_event(event_cmd_complete, delay, prepare_result(res, data, sz, errcode)); |
| 847 | 871 | } |
| 848 | 872 | |
| 849 | 873 | void psxcd_device::start_dma(UINT8 *mainram, UINT32 size) |
| r22512 | r22513 | |
| 895 | 919 | } |
| 896 | 920 | else |
| 897 | 921 | { |
| 898 | | command_result *res=global_alloc(command_result); |
| 899 | | res->res=intr_dataready; |
| 900 | | res->data[0]=status; |
| 901 | | res->sz=1; |
| 902 | | cmd_complete(res); |
| 922 | cmd_complete(prepare_result(intr_dataready)); |
| 903 | 923 | sectail++; |
| 904 | 924 | sectail %= sector_buffer_size; |
| 905 | 925 | |
| r22512 | r22513 | |
| 936 | 956 | { |
| 937 | 957 | verboselog(machine(), 1, "psxcd: autopause xa\n"); |
| 938 | 958 | |
| 939 | | command_result *res=global_alloc(command_result); |
| 940 | | res->res=intr_dataend; |
| 941 | | res->data[0]=status; |
| 942 | | res->sz=1; |
| 943 | | cmd_complete(res); |
| 959 | cmd_complete(prepare_result(intr_dataend)); |
| 944 | 960 | stop_read(); |
| 945 | 961 | } |
| 946 | 962 | } |
| r22512 | r22513 | |
| 964 | 980 | if(!cdrom_read_data(m_cdrom_handle, sector, secbuf[sectail], CD_TRACK_RAW_DONTCARE)) |
| 965 | 981 | { |
| 966 | 982 | stop_read(); // assume we've reached the end |
| 967 | | command_result *res=global_alloc(command_result); |
| 968 | | res->res=intr_dataend; |
| 969 | | res->data[0]=status; |
| 970 | | res->sz=1; |
| 971 | | cmd_complete(res); |
| 983 | cmd_complete(prepare_result(intr_dataend)); |
| 972 | 984 | return; |
| 973 | 985 | } |
| 974 | 986 | } |
| r22512 | r22513 | |
| 997 | 1009 | verboselog(machine(), 1, "psxcd: autopause cdda\n"); |
| 998 | 1010 | |
| 999 | 1011 | stop_read(); |
| 1000 | | command_result *res=global_alloc(command_result); |
| 1001 | | res->res=intr_dataend; |
| 1002 | | res->data[0]=status; |
| 1003 | | res->sz=1; |
| 1004 | | cmd_complete(res); |
| 1012 | cmd_complete(prepare_result(intr_dataend)); |
| 1005 | 1013 | return; |
| 1006 | 1014 | } |
| 1007 | 1015 | } |
| r22512 | r22513 | |
| 1053 | 1061 | if(!(mode & mode_cdda) && (cdrom_get_track_type(m_cdrom_handle, cdrom_get_track(m_cdrom_handle, sector + 150)) == CD_TRACK_AUDIO)) |
| 1054 | 1062 | { |
| 1055 | 1063 | stop_read(); |
| 1056 | | command_result *res=global_alloc(command_result); |
| 1057 | | res->res=intr_diskerror; |
| 1058 | | res->data[0]=status | status_error; |
| 1059 | | res->data[1]=0x40; |
| 1060 | | res->sz=2; |
| 1061 | | cmd_complete(res); |
| 1064 | cmd_complete(prepare_result(intr_diskerror, NULL, 0, 0x40)); |
| 1062 | 1065 | return; |
| 1063 | 1066 | } |
| 1064 | 1067 | send_result(intr_complete); |