trunk/src/mess/drivers/mz2000.c
| r17665 | r17666 | |
| 8 | 8 | Basically a simpler version of Sharp MZ-2500 |
| 9 | 9 | |
| 10 | 10 | TODO: |
| 11 | | - cassette interface; |
| 11 | - cassette interface, basically any program that's bigger than 8kb fails to load; |
| 12 | 12 | - implement remaining video capabilities |
| 13 | - add 80b compatibility support; |
| 14 | - Vosque (color): keyboard doesn't work properly; |
| 13 | 15 | |
| 14 | 16 | ****************************************************************************/ |
| 15 | 17 | |
| r17665 | r17666 | |
| 29 | 31 | #include "formats/basicdsk.h" |
| 30 | 32 | #include "formats/mz_cas.h" |
| 31 | 33 | |
| 34 | #define MASTER_CLOCK XTAL_17_73447MHz/5 /* TODO: was 4 MHz, but otherwise cassette won't work due of a bug with MZF support ... */ |
| 32 | 35 | |
| 33 | 36 | |
| 34 | 37 | class mz2000_state : public driver_device |
| r17665 | r17666 | |
| 46 | 49 | UINT8 m_gvram_enable; |
| 47 | 50 | UINT8 m_gvram_bank; |
| 48 | 51 | |
| 49 | | UINT8 m_key_mux,m_pio_latchb; |
| 52 | UINT8 m_key_mux; |
| 50 | 53 | |
| 51 | 54 | UINT8 m_old_portc; |
| 52 | 55 | UINT8 m_width80; |
| r17665 | r17666 | |
| 56 | 59 | UINT8 m_color_mode; |
| 57 | 60 | UINT8 m_has_fdc; |
| 58 | 61 | UINT8 m_hi_mode; |
| 62 | |
| 63 | UINT8 m_porta_latch; |
| 64 | UINT8 m_tape_ctrl; |
| 59 | 65 | DECLARE_READ8_MEMBER(mz2000_ipl_r); |
| 60 | 66 | DECLARE_READ8_MEMBER(mz2000_wram_r); |
| 61 | 67 | DECLARE_WRITE8_MEMBER(mz2000_wram_w); |
| r17665 | r17666 | |
| 577 | 583 | */ |
| 578 | 584 | UINT8 res = 0x80; |
| 579 | 585 | |
| 580 | | res |= (state->m_cass->input() > 0.0038) ? 0x40 : 0x00; |
| 581 | | res |= ((state->m_cass->get_state() & CASSETTE_MASK_UISTATE) == CASSETTE_PLAY) ? 0x00 : 0x20; |
| 582 | | res |= (state->m_cass->get_position() >= state->m_cass->get_length()) ? 0x08 : 0x00; |
| 586 | if(state->m_cass->get_image() != NULL) |
| 587 | { |
| 588 | res |= (state->m_cass->input() > 0.0038) ? 0x40 : 0x00; |
| 589 | res |= ((state->m_cass->get_state() & CASSETTE_MASK_UISTATE) == CASSETTE_PLAY) ? 0x00 : 0x20; |
| 590 | res |= (state->m_cass->get_position() >= state->m_cass->get_length()) ? 0x08 : 0x00; |
| 591 | } |
| 592 | else |
| 593 | res |= 0x20; |
| 594 | |
| 583 | 595 | res |= (device->machine().primary_screen->vblank()) ? 0x00 : 0x01; |
| 584 | 596 | |
| 585 | | // popmessage("%02x",res); |
| 586 | | |
| 587 | 597 | return res; |
| 588 | 598 | } |
| 589 | 599 | |
| r17665 | r17666 | |
| 596 | 606 | static WRITE8_DEVICE_HANDLER( mz2000_porta_w ) |
| 597 | 607 | { |
| 598 | 608 | /* |
| 599 | | TODO: it's likely to be a 0->1 transition |
| 609 | These are enabled thru a 0->1 transition |
| 600 | 610 | x--- ---- tape "APSS" |
| 601 | 611 | -x-- ---- tape "APLAY" |
| 602 | 612 | --x- ---- tape "AREW" |
| r17665 | r17666 | |
| 608 | 618 | */ |
| 609 | 619 | mz2000_state *state = device->machine().driver_data<mz2000_state>(); |
| 610 | 620 | |
| 611 | | if((data & 8) == 0) // stop |
| 621 | if((state->m_tape_ctrl & 0x80) == 0 && data & 0x80) |
| 612 | 622 | { |
| 623 | //printf("Tape APSS control\n"); |
| 624 | } |
| 625 | |
| 626 | if((state->m_tape_ctrl & 0x40) == 0 && data & 0x40) |
| 627 | { |
| 628 | //printf("Tape APLAY control\n"); |
| 629 | } |
| 630 | |
| 631 | if((state->m_tape_ctrl & 0x20) == 0 && data & 0x20) |
| 632 | { |
| 633 | //printf("Tape AREW control\n"); |
| 634 | } |
| 635 | |
| 636 | if((state->m_tape_ctrl & 0x10) == 0 && data & 0x10) |
| 637 | { |
| 638 | //printf("reverse video control\n"); |
| 639 | } |
| 640 | |
| 641 | if((state->m_tape_ctrl & 0x08) == 0 && data & 0x08) // stop |
| 642 | { |
| 613 | 643 | state->m_cass->change_state(CASSETTE_MOTOR_DISABLED,CASSETTE_MASK_MOTOR); |
| 614 | 644 | state->m_cass->change_state(CASSETTE_STOPPED,CASSETTE_MASK_UISTATE); |
| 615 | 645 | } |
| 616 | | if((data & 4) == 0) // play |
| 646 | |
| 647 | if((state->m_tape_ctrl & 0x04) == 0 && data & 0x04) // play |
| 617 | 648 | { |
| 618 | 649 | state->m_cass->change_state(CASSETTE_MOTOR_ENABLED,CASSETTE_MASK_MOTOR); |
| 619 | 650 | state->m_cass->change_state(CASSETTE_PLAY,CASSETTE_MASK_UISTATE); |
| 620 | 651 | } |
| 652 | |
| 653 | if((state->m_tape_ctrl & 0x02) == 0 && data & 0x02) |
| 654 | { |
| 655 | //printf("Tape FF control\n"); |
| 656 | } |
| 657 | |
| 658 | if((state->m_tape_ctrl & 0x01) == 0 && data & 0x01) |
| 659 | { |
| 660 | //printf("Tape Rewind control\n"); |
| 661 | } |
| 662 | |
| 663 | state->m_tape_ctrl = data; |
| 621 | 664 | } |
| 622 | 665 | |
| 623 | 666 | static WRITE8_DEVICE_HANDLER( mz2000_portb_w ) |
| r17665 | r17666 | |
| 673 | 716 | state->m_gvram_enable = ((data & 0xc0) == 0x80); |
| 674 | 717 | state->m_width80 = ((data & 0x20) >> 5); |
| 675 | 718 | state->m_key_mux = data & 0x1f; |
| 719 | |
| 720 | state->m_porta_latch = data; |
| 676 | 721 | } |
| 677 | 722 | |
| 678 | | static READ8_DEVICE_HANDLER( mz2000_pio1_porta_r ) |
| 723 | static READ8_DEVICE_HANDLER( mz2000_pio1_portb_r ) |
| 679 | 724 | { |
| 680 | 725 | mz2000_state *state = device->machine().driver_data<mz2000_state>(); |
| 681 | 726 | static const char *const keynames[] = { "KEY0", "KEY1", "KEY2", "KEY3", |
| r17665 | r17666 | |
| 691 | 736 | for(i=0;i<0xe;i++) |
| 692 | 737 | res &= device->machine().root_device().ioport(keynames[i])->read(); |
| 693 | 738 | |
| 694 | | state->m_pio_latchb = res; |
| 695 | | |
| 696 | 739 | return res; |
| 697 | 740 | } |
| 698 | 741 | |
| 699 | | state->m_pio_latchb = device->machine().root_device().ioport(keynames[state->m_key_mux & 0xf])->read(); |
| 700 | | |
| 701 | 742 | return device->machine().root_device().ioport(keynames[state->m_key_mux & 0xf])->read(); |
| 702 | 743 | } |
| 703 | 744 | |
| 745 | static READ8_DEVICE_HANDLER( mz2000_pio1_porta_r ) |
| 746 | { |
| 747 | mz2000_state *state = device->machine().driver_data<mz2000_state>(); |
| 748 | |
| 749 | return state->m_porta_latch; |
| 750 | } |
| 751 | |
| 704 | 752 | static Z80PIO_INTERFACE( mz2000_pio1_intf ) |
| 705 | 753 | { |
| 706 | 754 | DEVCB_NULL, |
| 707 | 755 | DEVCB_HANDLER( mz2000_pio1_porta_r ), |
| 708 | 756 | DEVCB_HANDLER( mz2000_pio1_porta_w ), |
| 709 | 757 | DEVCB_NULL, |
| 710 | | DEVCB_HANDLER( mz2000_pio1_porta_r ), |
| 758 | DEVCB_HANDLER( mz2000_pio1_portb_r ), |
| 711 | 759 | DEVCB_NULL, |
| 712 | 760 | DEVCB_NULL |
| 713 | 761 | }; |
| r17665 | r17666 | |
| 778 | 826 | |
| 779 | 827 | static MACHINE_CONFIG_START( mz2000, mz2000_state ) |
| 780 | 828 | /* basic machine hardware */ |
| 781 | | MCFG_CPU_ADD("maincpu",Z80, XTAL_17_73447MHz/5) /* TODO: was 4 MHz, but otherwise cassette won't work */ |
| 829 | MCFG_CPU_ADD("maincpu",Z80, MASTER_CLOCK) |
| 782 | 830 | MCFG_CPU_PROGRAM_MAP(mz2000_map) |
| 783 | 831 | MCFG_CPU_IO_MAP(mz2000_io) |
| 784 | 832 | |
| 785 | 833 | MCFG_MACHINE_RESET(mz2000) |
| 786 | 834 | |
| 787 | 835 | MCFG_I8255_ADD( "i8255_0", ppi8255_intf ) |
| 788 | | MCFG_Z80PIO_ADD( "z80pio_1", 4000000, mz2000_pio1_intf ) |
| 836 | MCFG_Z80PIO_ADD( "z80pio_1", MASTER_CLOCK, mz2000_pio1_intf ) |
| 789 | 837 | MCFG_PIT8253_ADD("pit", mz2000_pit8253_intf) |
| 790 | 838 | |
| 791 | 839 | MCFG_MB8877_ADD("mb8877a",mz2000_mb8877a_interface) |