src/emu/video/pc_vga.c
| r14322 | r14323 | |
| 162 | 162 | { |
| 163 | 163 | UINT8 bank_r,bank_w; |
| 164 | 164 | UINT8 rgb8_en; |
| 165 | UINT8 rgb15_en; |
| 166 | UINT8 id; |
| 165 | 167 | }svga; |
| 166 | 168 | |
| 167 | 169 | #define REG(x) vga.crtc.data[x] |
| r14322 | r14323 | |
| 198 | 200 | |
| 199 | 201 | #define TEXT_COPY_9COLUMN(ch) (((ch & 0xe0) == 0xc0)&&(vga.attribute.data[0x10]&4)) |
| 200 | 202 | |
| 203 | // Special values for SVGA Trident - Mode Vesa 110h |
| 204 | #define TLINES (LINES) |
| 205 | #define TGA_COLUMNS (EGA_COLUMNS) |
| 206 | #define TGA_START_ADDRESS (vga.crtc.start_addr<<2) |
| 207 | #define TGA_LINE_LENGTH (vga.crtc.offset<<3) |
| 201 | 208 | |
| 209 | |
| 202 | 210 | /*************************************************************************** |
| 203 | 211 | |
| 204 | 212 | Static declarations |
| r14322 | r14323 | |
| 522 | 530 | } |
| 523 | 531 | } |
| 524 | 532 | |
| 533 | static void svga_vh_rgb15(running_machine &machine, bitmap_rgb32 &bitmap, const rectangle &cliprect) |
| 534 | { |
| 535 | #define MV(x) (vga.memory[x]+(vga.memory[x+1]<<8)) |
| 536 | #define IV 0xff000000 |
| 537 | int height = vga.crtc.maximum_scan_line * (vga.crtc.scan_doubling + 1); |
| 538 | int xi; |
| 539 | int yi; |
| 540 | int xm; |
| 541 | |
| 542 | int pos, line, column, c, addr, curr_addr; |
| 543 | |
| 544 | UINT32 *bitmapline; |
| 545 | UINT16 mask_comp; |
| 546 | |
| 547 | /* line compare is screen sensitive */ |
| 548 | mask_comp = 0xff | (TLINES & 0x300); |
| 549 | curr_addr = 0; |
| 550 | yi=0; |
| 551 | for (addr = TGA_START_ADDRESS, line=0; line<TLINES; line+=height, addr+=TGA_LINE_LENGTH, curr_addr+=TGA_LINE_LENGTH) |
| 552 | { |
| 553 | if(line>500) return; |
| 554 | bitmapline = &bitmap.pix32(line); |
| 555 | addr %= vga.svga_intf.vram_size; |
| 556 | for (pos=addr, c=0, column=0; column<TGA_COLUMNS; column++, c+=8, pos+=0x10) |
| 557 | { |
| 558 | if(pos + 0x10 > vga.svga_intf.vram_size) |
| 559 | return; |
| 560 | for(xi=0,xm=0;xi<8;xi++,xm+=2) |
| 561 | { |
| 562 | if(!machine.primary_screen->visible_area().contains(c+xi, line + yi)) |
| 563 | continue; |
| 564 | bitmapline[c+xi] = IV|(MV(pos+xm)&0x7c00)<<9 |(MV(pos+xm)&0x3e0)<<6|(MV(pos+xm)&0x1f)<<3; |
| 565 | } |
| 566 | } |
| 567 | } |
| 568 | } |
| 569 | |
| 525 | 570 | enum |
| 526 | 571 | { |
| 527 | 572 | SCREEN_OFF = 0, |
| r14322 | r14323 | |
| 531 | 576 | CGA_MODE, |
| 532 | 577 | MONO_MODE, |
| 533 | 578 | RGB8_MODE, |
| 579 | RGB15_MODE, |
| 534 | 580 | SVGA_HACK |
| 535 | 581 | }; |
| 536 | 582 | |
| r14322 | r14323 | |
| 577 | 623 | { |
| 578 | 624 | return RGB8_MODE; |
| 579 | 625 | } |
| 626 | else if (svga.rgb15_en&0x30) |
| 627 | { |
| 628 | return RGB15_MODE; |
| 629 | } |
| 580 | 630 | else if (!GRAPHIC_MODE) |
| 581 | 631 | { |
| 582 | 632 | //proc = vga_vh_text; |
| r14322 | r14323 | |
| 632 | 682 | case CGA_MODE: vga_vh_cga (screen.machine(), bitmap, cliprect); break; |
| 633 | 683 | case MONO_MODE: vga_vh_mono(screen.machine(), bitmap, cliprect); break; |
| 634 | 684 | case RGB8_MODE: svga_vh_rgb8(screen.machine(), bitmap, cliprect); break; |
| 685 | case RGB15_MODE: svga_vh_rgb15(screen.machine(), bitmap, cliprect); break; |
| 635 | 686 | case SVGA_HACK: vga.svga_intf.choosevideomode(screen.machine(), bitmap, cliprect, vga.sequencer.data, vga.crtc.data, vga.gc.data, &w, &h); break; |
| 636 | 687 | } |
| 637 | 688 | |
| r14322 | r14323 | |
| 1719 | 1770 | else |
| 1720 | 1771 | vga_mem_w(space,offset,data); |
| 1721 | 1772 | } |
| 1773 | |
| 1774 | /****************************************** |
| 1775 | |
| 1776 | Trident implementation |
| 1777 | |
| 1778 | ******************************************/ |
| 1779 | |
| 1780 | void pc_svga_trident_io_init(running_machine &machine, address_space *mem_space, offs_t mem_offset, address_space *io_space, offs_t port_offset) |
| 1781 | { |
| 1782 | int buswidth; |
| 1783 | UINT64 mask = 0; |
| 1784 | |
| 1785 | buswidth = machine.firstcpu->memory().space_config(AS_PROGRAM)->m_databus_width; |
| 1786 | switch(buswidth) |
| 1787 | { |
| 1788 | case 8: |
| 1789 | mask = 0; |
| 1790 | break; |
| 1791 | |
| 1792 | case 16: |
| 1793 | mask = 0xffff; |
| 1794 | break; |
| 1795 | |
| 1796 | case 32: |
| 1797 | mask = 0xffffffff; |
| 1798 | break; |
| 1799 | |
| 1800 | case 64: |
| 1801 | mask = -1; |
| 1802 | break; |
| 1803 | |
| 1804 | default: |
| 1805 | fatalerror("VGA: Bus width %d not supported", buswidth); |
| 1806 | break; |
| 1807 | } |
| 1808 | io_space->install_legacy_readwrite_handler(port_offset + 0x3b0, port_offset + 0x3bf, FUNC(vga_port_03b0_r), FUNC(vga_port_03b0_w), mask); |
| 1809 | io_space->install_legacy_readwrite_handler(port_offset + 0x3c0, port_offset + 0x3cf, FUNC(trident_03c0_r), FUNC(trident_03c0_w), mask); |
| 1810 | io_space->install_legacy_readwrite_handler(port_offset + 0x3d0, port_offset + 0x3df, FUNC(trident_03d0_r), FUNC(trident_03d0_w), mask); |
| 1811 | |
| 1812 | mem_space->install_legacy_readwrite_handler(mem_offset + 0x00000, mem_offset + 0x1ffff, FUNC(trident_mem_r), FUNC(trident_mem_w), mask); |
| 1813 | |
| 1814 | // D3h = TGUI9660XGi |
| 1815 | svga.id = 0xd3; // TODO: hardcoded for California Chase |
| 1816 | } |
| 1817 | |
| 1818 | static UINT8 trident_seq_reg_read(running_machine &machine, UINT8 index) |
| 1819 | { |
| 1820 | UINT8 res; |
| 1821 | |
| 1822 | res = 0xff; |
| 1823 | |
| 1824 | if(index <= 0x04) |
| 1825 | res = vga.sequencer.data[index]; |
| 1826 | else |
| 1827 | { |
| 1828 | switch(index) |
| 1829 | { |
| 1830 | case 0x0b: |
| 1831 | res = svga.id; |
| 1832 | // TODO: new mode registers selected |
| 1833 | break; |
| 1834 | case 0x0d: |
| 1835 | res = svga.rgb15_en; |
| 1836 | break; |
| 1837 | } |
| 1838 | } |
| 1839 | |
| 1840 | return res; |
| 1841 | } |
| 1842 | |
| 1843 | static void trident_seq_reg_write(running_machine &machine, UINT8 index, UINT8 data) |
| 1844 | { |
| 1845 | if(index <= 0x04) |
| 1846 | { |
| 1847 | vga.sequencer.data[vga.sequencer.index] = data; |
| 1848 | seq_reg_write(machine,vga.sequencer.index,data); |
| 1849 | recompute_params(machine); |
| 1850 | } |
| 1851 | else |
| 1852 | { |
| 1853 | switch(index) |
| 1854 | { |
| 1855 | case 0x0b: |
| 1856 | // TODO: old mode registers selected |
| 1857 | break; |
| 1858 | case 0x0d: |
| 1859 | svga.rgb15_en = data & 0x30; // TODO: doesn't match documentation |
| 1860 | break; |
| 1861 | } |
| 1862 | } |
| 1863 | } |
| 1864 | |
| 1865 | |
| 1866 | READ8_HANDLER(trident_03c0_r) |
| 1867 | { |
| 1868 | UINT8 res; |
| 1869 | |
| 1870 | switch(offset) |
| 1871 | { |
| 1872 | case 0x05: |
| 1873 | res = trident_seq_reg_read(space->machine(),vga.sequencer.index); |
| 1874 | break; |
| 1875 | default: |
| 1876 | res = vga_port_03c0_r(space,offset); |
| 1877 | break; |
| 1878 | } |
| 1879 | |
| 1880 | return res; |
| 1881 | } |
| 1882 | |
| 1883 | WRITE8_HANDLER(trident_03c0_w) |
| 1884 | { |
| 1885 | switch(offset) |
| 1886 | { |
| 1887 | case 0x05: |
| 1888 | trident_seq_reg_write(space->machine(),vga.sequencer.index,data); |
| 1889 | break; |
| 1890 | default: |
| 1891 | vga_port_03c0_w(space,offset,data); |
| 1892 | break; |
| 1893 | } |
| 1894 | } |
| 1895 | |
| 1896 | |
| 1897 | READ8_HANDLER(trident_03d0_r) |
| 1898 | { |
| 1899 | UINT8 res = 0xff; |
| 1900 | |
| 1901 | if (CRTC_PORT_ADDR == 0x3d0) |
| 1902 | { |
| 1903 | switch(offset) |
| 1904 | { |
| 1905 | case 8: |
| 1906 | res = svga.bank_w & 0x1f; // TODO: a lot more complex than this |
| 1907 | break; |
| 1908 | default: |
| 1909 | res = vga_port_03d0_r(space,offset); |
| 1910 | break; |
| 1911 | } |
| 1912 | } |
| 1913 | |
| 1914 | return res; |
| 1915 | } |
| 1916 | |
| 1917 | WRITE8_HANDLER(trident_03d0_w) |
| 1918 | { |
| 1919 | if (CRTC_PORT_ADDR == 0x3d0) |
| 1920 | { |
| 1921 | switch(offset) |
| 1922 | { |
| 1923 | case 8: |
| 1924 | svga.bank_w = data & 0x1f; // TODO: a lot more complex than this |
| 1925 | break; |
| 1926 | default: |
| 1927 | vga_port_03d0_w(space,offset,data); |
| 1928 | break; |
| 1929 | } |
| 1930 | } |
| 1931 | } |
| 1932 | |
| 1933 | READ8_HANDLER( trident_mem_r ) |
| 1934 | { |
| 1935 | if (svga.rgb15_en & 0x30) |
| 1936 | { |
| 1937 | int data; |
| 1938 | if(offset & 0x10000) // TODO: old reg mode actually CAN read to the upper bank |
| 1939 | return 0; |
| 1940 | data=vga.memory[offset + (svga.bank_w*0x10000)]; |
| 1941 | return data; |
| 1942 | } |
| 1943 | |
| 1944 | return vga_mem_r(space,offset); |
| 1945 | } |
| 1946 | |
| 1947 | WRITE8_HANDLER( trident_mem_w ) |
| 1948 | { |
| 1949 | if (svga.rgb15_en & 0x30) |
| 1950 | { |
| 1951 | if(offset & 0x10000) // TODO: old reg mode actually CAN write to the upper bank |
| 1952 | return; |
| 1953 | vga.memory[offset + (svga.bank_w*0x10000)]= data; |
| 1954 | return; |
| 1955 | } |
| 1956 | |
| 1957 | vga_mem_w(space,offset,data); |
| 1958 | } |