src/mess/drivers/pc8801.c
| r10171 | r10172 | |
| 147 | 147 | #include "sound/beep.h" |
| 148 | 148 | //#include "includes/pc8801.h" |
| 149 | 149 | |
| 150 | //#define USE_PROPER_I8214 |
| 151 | |
| 150 | 152 | static UINT8 i8255_0_pc,i8255_1_pc; |
| 151 | 153 | static UINT8 fdc_irq_opcode; |
| 152 | 154 | static UINT8 ext_rom_bank,gfx_ctrl,vram_sel,misc_ctrl,device_ctrl_data; |
| r10171 | r10172 | |
| 159 | 161 | static UINT8 extram_mode,extram_bank; |
| 160 | 162 | static UINT8 txt_width, txt_color; |
| 161 | 163 | static int vblank_pos; |
| 164 | #ifdef USE_PROPER_I8214 |
| 165 | static UINT8 m_int_mask,m_int_state; |
| 166 | #else |
| 162 | 167 | static UINT8 i8214_irq_level; |
| 163 | 168 | static UINT8 vrtc_irq_mask,vrtc_irq_latch; |
| 164 | 169 | static UINT8 timer_irq_mask,timer_irq_latch; |
| 165 | 170 | static UINT8 sound_irq_mask,sound_irq_latch; |
| 171 | #endif |
| 166 | 172 | |
| 167 | | |
| 168 | 173 | /* |
| 169 | 174 | CRTC command params: |
| 170 | 175 | 0. CRTC reset |
| r10171 | r10172 | |
| 876 | 881 | vram_sel = offset & 3; |
| 877 | 882 | } |
| 878 | 883 | |
| 884 | #ifdef USE_PROPER_I8214 |
| 885 | |
| 886 | static WRITE8_HANDLER( i8214_irq_level_w ) |
| 887 | { |
| 888 | i8214_b_w(space->machine->device("i8214"), 0, (data & 0x0f)); |
| 889 | } |
| 890 | |
| 891 | static WRITE8_HANDLER( i8214_irq_mask_w ) |
| 892 | { |
| 893 | m_int_mask = BITSWAP8((data & 0x07) | (m_int_mask & 0xf8),7,6,5,4,3,0,1,2); |
| 894 | } |
| 895 | |
| 896 | |
| 897 | #else |
| 879 | 898 | static WRITE8_HANDLER( pc8801_irq_level_w ) |
| 880 | 899 | { |
| 881 | 900 | if(data & 8) |
| r10171 | r10172 | |
| 899 | 918 | //if(data & 4) |
| 900 | 919 | // printf("IRQ mask %02x\n",data); |
| 901 | 920 | } |
| 921 | #endif |
| 902 | 922 | |
| 903 | 923 | static READ8_HANDLER( pc8801_window_bank_r ) |
| 904 | 924 | { |
| r10171 | r10172 | |
| 925 | 945 | { |
| 926 | 946 | misc_ctrl = data; |
| 927 | 947 | |
| 948 | #ifdef USE_PROPER_I8214 |
| 949 | m_int_mask = (m_int_mask & 0xef) | ((data & 0x80) ? 0x00 : 0x10); |
| 950 | #else |
| 928 | 951 | sound_irq_mask = ((data & 0x80) == 0); |
| 929 | 952 | |
| 930 | 953 | if(sound_irq_mask == 0) |
| 931 | 954 | sound_irq_latch = 0; |
| 955 | #endif |
| 932 | 956 | } |
| 933 | 957 | |
| 934 | 958 | static WRITE8_HANDLER( pc8801_palram_w ) |
| r10171 | r10172 | |
| 1203 | 1227 | // AM_RANGE(0xdc, 0xdf) AM_NOP /* MODEM */ |
| 1204 | 1228 | AM_RANGE(0xe2, 0xe2) AM_READWRITE(pc8801_extram_mode_r,pc8801_extram_mode_w) /* expand RAM mode */ |
| 1205 | 1229 | AM_RANGE(0xe3, 0xe3) AM_READWRITE(pc8801_extram_bank_r,pc8801_extram_bank_w) /* expand RAM bank */ |
| 1230 | #ifdef USE_PROPER_I8214 |
| 1231 | AM_RANGE(0xe4, 0xe4) AM_WRITE(i8214_irq_level_w) |
| 1232 | AM_RANGE(0xe6, 0xe6) AM_WRITE(i8214_irq_mask_w) |
| 1233 | #else |
| 1206 | 1234 | AM_RANGE(0xe4, 0xe4) AM_WRITE(pc8801_irq_level_w) |
| 1207 | 1235 | AM_RANGE(0xe6, 0xe6) AM_WRITE(pc8801_irq_mask_w) |
| 1208 | | // AM_RANGE(0xe7, 0xe7) AM_NOP /* (unknown) */ |
| 1236 | #endif |
| 1237 | // AM_RANGE(0xe7, 0xe7) AM_NOP /* Arcus writes here, almost likely to be a mirror of above */ |
| 1209 | 1238 | AM_RANGE(0xe8, 0xeb) AM_READWRITE(pc8801_kanji_r, pc8801_kanji_w) |
| 1210 | 1239 | AM_RANGE(0xec, 0xef) AM_READWRITE(pc8801_kanji_lv2_r, pc8801_kanji_lv2_w) |
| 1211 | 1240 | // AM_RANGE(0xf0, 0xf1) AM_NOP /* Kana to Kanji dictionary ROM select (not yet) */ |
| r10171 | r10172 | |
| 1611 | 1640 | DEVCB_NULL |
| 1612 | 1641 | }; |
| 1613 | 1642 | |
| 1614 | | /* YM2203 Interface */ |
| 1615 | | static void pc8801_sound_irq( device_t *device, int irq ) |
| 1616 | | { |
| 1617 | | if(sound_irq_mask) |
| 1618 | | { |
| 1619 | | sound_irq_latch = 1; |
| 1620 | | cputag_set_input_line(device->machine,"maincpu",0,HOLD_LINE); |
| 1621 | | } |
| 1622 | | } |
| 1623 | | |
| 1624 | | /* TODO: mouse routing (that's why I don't use DEVCB_INPUT_PORT here) */ |
| 1625 | | static READ8_DEVICE_HANDLER( opn_porta_r ) { return input_port_read(device->machine, "OPN_PA"); } |
| 1626 | | static READ8_DEVICE_HANDLER( opn_portb_r ) { return input_port_read(device->machine, "OPN_PB"); } |
| 1627 | | |
| 1628 | | static const ym2203_interface pc88_ym2203_intf = |
| 1629 | | { |
| 1630 | | { |
| 1631 | | AY8910_LEGACY_OUTPUT, |
| 1632 | | AY8910_DEFAULT_LOADS, |
| 1633 | | DEVCB_HANDLER(opn_porta_r), |
| 1634 | | DEVCB_HANDLER(opn_portb_r), |
| 1635 | | DEVCB_NULL, |
| 1636 | | DEVCB_NULL |
| 1637 | | }, |
| 1638 | | pc8801_sound_irq |
| 1639 | | }; |
| 1640 | | |
| 1641 | 1643 | /* Floppy Configuration */ |
| 1642 | 1644 | |
| 1643 | 1645 | static const floppy_config pc88_floppy_config = |
| r10171 | r10172 | |
| 1662 | 1664 | NULL |
| 1663 | 1665 | }; |
| 1664 | 1666 | |
| 1667 | #ifdef USE_PROPER_I8214 |
| 1668 | void pc8801_raise_irq(running_machine *machine,UINT8 mask) |
| 1669 | { |
| 1670 | m_int_state |= mask; |
| 1671 | |
| 1672 | i8214_r_w(machine->device("i8214"), 0, ~(m_int_state & m_int_mask)); |
| 1673 | } |
| 1674 | |
| 1675 | static WRITE_LINE_DEVICE_HANDLER( pic_int_w ) |
| 1676 | { |
| 1677 | if (state == ASSERT_LINE) |
| 1678 | { |
| 1679 | cpu_set_input_line(device, INPUT_LINE_IRQ0, ASSERT_LINE); |
| 1680 | } |
| 1681 | } |
| 1682 | |
| 1683 | static I8214_INTERFACE( pic_intf ) |
| 1684 | { |
| 1685 | DEVCB_DEVICE_LINE("maincpu", pic_int_w), |
| 1686 | DEVCB_NULL |
| 1687 | }; |
| 1688 | |
| 1665 | 1689 | static IRQ_CALLBACK( pc8801_irq_callback ) |
| 1666 | 1690 | { |
| 1691 | UINT8 vector = (i8214_a_r(device->machine->device("i8214"), 0)); // |
| 1692 | |
| 1693 | printf("Interrupt Acknowledge Vector: %02x\n", vector); |
| 1694 | m_int_state &= ~vector; |
| 1695 | |
| 1696 | cputag_set_input_line(device->machine,"maincpu", INPUT_LINE_IRQ0, CLEAR_LINE); |
| 1697 | i8214_r_w(device->machine->device("i8214"), 0, ~(m_int_state & m_int_mask)); |
| 1698 | |
| 1699 | return 1*2; |
| 1700 | } |
| 1701 | |
| 1702 | static void pc8801_sound_irq( device_t *device, int irq ) |
| 1703 | { |
| 1704 | |
| 1705 | } |
| 1706 | |
| 1707 | static TIMER_CALLBACK( pc8801_rtc_irq ) |
| 1708 | { |
| 1709 | //pc8801_raise_irq(machine,2); |
| 1710 | //if(m_int_mask & 4) |
| 1711 | // cputag_set_input_line(machine, "maincpu", INPUT_LINE_IRQ0, ASSERT_LINE); |
| 1712 | } |
| 1713 | |
| 1714 | static INTERRUPT_GEN( pc8801_vrtc_irq ) |
| 1715 | { |
| 1716 | pc8801_raise_irq(device->machine,1); |
| 1717 | //if(m_int_mask & 2) |
| 1718 | // cputag_set_input_line(device->machine, "maincpu", INPUT_LINE_IRQ0, ASSERT_LINE); |
| 1719 | } |
| 1720 | |
| 1721 | #else |
| 1722 | static IRQ_CALLBACK( pc8801_irq_callback ) |
| 1723 | { |
| 1667 | 1724 | if(i8214_irq_level >= 5 && sound_irq_latch) |
| 1668 | 1725 | { |
| 1669 | 1726 | sound_irq_latch = 0; |
| r10171 | r10172 | |
| 1681 | 1738 | } |
| 1682 | 1739 | |
| 1683 | 1740 | printf("IRQ triggered but no vector on the bus! %02x %02x %02x %02x\n",i8214_irq_level,sound_irq_latch,vrtc_irq_latch,timer_irq_latch); |
| 1741 | if(sound_irq_latch) |
| 1742 | return 4*2; |
| 1743 | |
| 1684 | 1744 | return 2*2; //TODO: mustn't happen, it does if you press shift on N88-BASIC |
| 1685 | 1745 | } |
| 1686 | 1746 | |
| 1747 | static void pc8801_sound_irq( device_t *device, int irq ) |
| 1748 | { |
| 1749 | if(sound_irq_mask) |
| 1750 | { |
| 1751 | sound_irq_latch = 1; |
| 1752 | cputag_set_input_line(device->machine,"maincpu",0,HOLD_LINE); |
| 1753 | } |
| 1754 | } |
| 1755 | |
| 1687 | 1756 | static TIMER_CALLBACK( pc8801_rtc_irq ) |
| 1688 | 1757 | { |
| 1689 | 1758 | if(timer_irq_mask) |
| r10171 | r10172 | |
| 1693 | 1762 | } |
| 1694 | 1763 | } |
| 1695 | 1764 | |
| 1765 | static INTERRUPT_GEN( pc8801_vrtc_irq ) |
| 1766 | { |
| 1767 | if(vrtc_irq_mask) |
| 1768 | { |
| 1769 | vrtc_irq_latch = 1; |
| 1770 | cpu_set_input_line(device,0,HOLD_LINE); |
| 1771 | } |
| 1772 | } |
| 1773 | #endif |
| 1774 | |
| 1696 | 1775 | static MACHINE_START( pc8801 ) |
| 1697 | 1776 | { |
| 1698 | 1777 | cpu_set_irq_callback(machine->device("maincpu"), pc8801_irq_callback); |
| r10171 | r10172 | |
| 1735 | 1814 | beep_set_frequency(machine->device("beeper"),2400); |
| 1736 | 1815 | beep_set_state(machine->device("beeper"),0); |
| 1737 | 1816 | |
| 1817 | #ifdef USE_PROPER_I8214 |
| 1738 | 1818 | { |
| 1819 | /* initialize I8214 */ |
| 1820 | i8214_etlg_w(machine->device("i8214"), 1); |
| 1821 | i8214_inte_w(machine->device("i8214"), 1); |
| 1822 | } |
| 1823 | #else |
| 1824 | { |
| 1739 | 1825 | vrtc_irq_mask = 0; |
| 1740 | 1826 | vrtc_irq_latch = 0; |
| 1741 | 1827 | timer_irq_mask = 0; |
| r10171 | r10172 | |
| 1744 | 1830 | sound_irq_latch = 0; |
| 1745 | 1831 | i8214_irq_level = 0; |
| 1746 | 1832 | } |
| 1833 | #endif |
| 1747 | 1834 | |
| 1748 | 1835 | { |
| 1749 | 1836 | dma_address[2] = 0xf300; |
| r10171 | r10172 | |
| 1779 | 1866 | {FLOPPY_0, FLOPPY_1, NULL, NULL} |
| 1780 | 1867 | }; |
| 1781 | 1868 | |
| 1782 | | static INTERRUPT_GEN( pc8801_vrtc_irq ) |
| 1869 | /* YM2203 Interface */ |
| 1870 | |
| 1871 | /* TODO: mouse routing (that's why I don't use DEVCB_INPUT_PORT here) */ |
| 1872 | static READ8_DEVICE_HANDLER( opn_porta_r ) { return input_port_read(device->machine, "OPN_PA"); } |
| 1873 | static READ8_DEVICE_HANDLER( opn_portb_r ) { return input_port_read(device->machine, "OPN_PB"); } |
| 1874 | |
| 1875 | static const ym2203_interface pc88_ym2203_intf = |
| 1783 | 1876 | { |
| 1784 | | if(vrtc_irq_mask) |
| 1785 | 1877 | { |
| 1786 | | vrtc_irq_latch = 1; |
| 1787 | | cpu_set_input_line(device,0,HOLD_LINE); |
| 1788 | | } |
| 1789 | | } |
| 1878 | AY8910_LEGACY_OUTPUT, |
| 1879 | AY8910_DEFAULT_LOADS, |
| 1880 | DEVCB_HANDLER(opn_porta_r), |
| 1881 | DEVCB_HANDLER(opn_portb_r), |
| 1882 | DEVCB_NULL, |
| 1883 | DEVCB_NULL |
| 1884 | }, |
| 1885 | pc8801_sound_irq |
| 1886 | }; |
| 1790 | 1887 | |
| 1888 | #define MASTER_CLOCK XTAL_4MHz |
| 1889 | |
| 1791 | 1890 | static MACHINE_CONFIG_START( pc8801, driver_device ) |
| 1792 | 1891 | /* main CPU */ |
| 1793 | | MCFG_CPU_ADD("maincpu", Z80, 4000000) /* 4 MHz */ |
| 1892 | MCFG_CPU_ADD("maincpu", Z80, MASTER_CLOCK) /* 4 MHz */ |
| 1794 | 1893 | MCFG_CPU_PROGRAM_MAP(pc8801_mem) |
| 1795 | 1894 | MCFG_CPU_IO_MAP(pc8801_io) |
| 1796 | 1895 | MCFG_CPU_VBLANK_INT("screen", pc8801_vrtc_irq) |
| 1797 | 1896 | |
| 1798 | 1897 | /* sub CPU(5 inch floppy drive) */ |
| 1799 | | MCFG_CPU_ADD("fdccpu", Z80, 4000000) /* 4 MHz */ |
| 1898 | MCFG_CPU_ADD("fdccpu", Z80, MASTER_CLOCK) /* 4 MHz */ |
| 1800 | 1899 | MCFG_CPU_PROGRAM_MAP(pc8801fdc_mem) |
| 1801 | 1900 | MCFG_CPU_IO_MAP(pc8801fdc_io) |
| 1802 | 1901 | |
| r10171 | r10172 | |
| 1809 | 1908 | MCFG_I8255A_ADD( "d8255_slave", slave_fdd_intf ) |
| 1810 | 1909 | |
| 1811 | 1910 | MCFG_UPD765A_ADD("upd765", pc8801_upd765_interface) |
| 1911 | #ifdef USE_PROPER_I8214 |
| 1912 | MCFG_I8214_ADD("i8214", MASTER_CLOCK, pic_intf) |
| 1913 | #endif |
| 1812 | 1914 | //MCFG_UPD1990A_ADD("upd1990a", XTAL_32_768kHz, pc88_upd1990a_intf) |
| 1813 | 1915 | //MCFG_CENTRONICS_ADD("centronics", standard_centronics) |
| 1814 | 1916 | //MCFG_CASSETTE_ADD("cassette", pc88_cassette_config) |
| r10171 | r10172 | |
| 1831 | 1933 | |
| 1832 | 1934 | /* sound hardware */ |
| 1833 | 1935 | MCFG_SPEAKER_STANDARD_MONO("mono") |
| 1834 | | MCFG_SOUND_ADD("opn", YM2203, 4000000) //unknown clock |
| 1936 | MCFG_SOUND_ADD("opn", YM2203, MASTER_CLOCK) |
| 1835 | 1937 | MCFG_SOUND_CONFIG(pc88_ym2203_intf) |
| 1836 | 1938 | MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25) |
| 1837 | 1939 | |